Pagina 205 del testo
Ricerca sequenziale
Il codice analizzato è il seguente
def ricerca_sequenziale(vettore, n, x):
trovato = False # c1
i = 0 # c2
while(i < n) and (not trovato): # c3 c4 c5
if(vettore[i] == x): # c6
trovato = True # c7
i = i+1 # c8
return trovato # c9
Il codice presenta operazioni diverse (assegnazioni, confronti, aritmetiche, logiche).
Per semplificare i calcoli si decide di trascurare le differenze esistenti tra i tempi di esecuzione delle diverse operazioni e di stabilire un tempo costante per tutte.
I valori di T(n) sono
- Vettore vuoto: c1+c2+(c3+c4+c5)+c9 = 6
- Elemento in posizione 0: c1+c2+(c3+c4+c5+c6+c7+c8)+(c3+c4+c5)+c9 = 12
- Elemento in posizione 1: c1+c2+(c3+c4+c5+c6+c8)+(c3+c4+c5+c6+c7+c8)+(c3+c4+c5)+c9 = 17
- Elemento in posizione 2: c1+c2+(c3+c4+c5+c6+c8)+(c3+c4+c5+c6+c8)+(c3+c4+c5+c6+c7+c8)+(c3+c4+c5)+c10 = 22
- …
- Elemento in posizione p: c1+c2+(c3+c4+c5+c6+c8)+…+(c3+c4+c5+c6+c8)+(c3+c4+c5+c6+c7+c8)+(c3+c4+c5)+c9 = 5*p+12
- …
- Elemento in posizione n-1: 5*(n-1)+12
- Elemento non presente: 5*n+12
Analizziamo i casi più interessanti
- Caso ottimo, quando il vettore è vuoto: T(n) = 6
- … oppure l’elemento x compare alla posizione 0: T(n) = 12
- Caso pessimo, l’elemento x compare alla posizione n-1: T(n) = 5*(n-1)+12
- … oppure se l’elemento x non è presente: T(n) = 5n+12
- Caso medio, supponiamo di effettuare n ricerche con l’elemento presente alle diverse posizioni 0, 1, …, n-1
T(n) =
= =
=
=
.
Conclusioni
Il tempo richiesto dall’algoritmo di ricerca sequenziale è, tranne che nei casi banali, una funzione lineare di n, il numero di elementi presenti nel vettore:
Ricerca binaria
Analizziamo il codice
def ricerca_binaria(vettore, n, x):
primo = 0 # c1
ultimo = n-1 # c2
trovato = 0 # c3
while(primo <= ultimo) and (not trovato): # c4 c5 c6
centro = (primo+ultimo) // 2 # c7
if(vettore[centro] == x): # c8
trovato = centro # c9
elif(vettore[centro] < x): # c10
primo = centro+1 # c11
else:
ultimo = centro-1 # c12
return trovato # c13
Utilizzando la tecnica di calcolo della complessità in tempo utilizzata per la ricerca sequenziale, i valori di T(n) sono
- Vettore vuoto: c1+c2+c3+(c4+c5+c6)+c13 = 7
- Elemento in 1° posizione centrale: c1+c2+c3+(c4+c5+c6+c7+c8+c9)+(c4+c5+c6)+c13 = 13
- Elemento in 2° posizione centrale: c1+c2+c3+(c4+c5+c6+c7+c8+c10+c11|12)+(c4+c5+c6+c7+c8+c9)+(c4+c5+c6)+c13 = 20
- Elemento in 3° posizione centrale: c1+c2+c3+(c4+c5+c6+c7+c8+c10+c11|12)+(c4+c5+c6+c7+c8+c10+c11|12)+(c4+c5+c6+c7+c8+c9)+(c4+c5+c6)+c13 = 27
- …
- Un accesso nel while senza successo richiede 7 operazioni, con successo 6.
Consideriamo un costo fisso 7… - Elemento trovato dopo m accessi: 7*m+13
- Elemento non trovato dopo m accessi: 7*m+13
Analizziamo i casi più interessanti
- Caso ottimo, quando il vettore è vuoto: T(n) = 7
- … oppure l’elemento x compare alla posizione centrale: T(n) = 13
- Caso pessimo, l’elemento x compare dopo m accessi: T(n) = 7*m+13
- … oppure se l’elemento x non è presente: T(n) = 7*m+13
con m il numero di volte che viene eseguito il ciclo while.
Quanto vale m?
La dimensione del vettore sul quale si effettua la ricerca si dimezza a ogni passo
->
->
->
-> … -> 2 ->
= 1
Quando il valore della potenza di 2 raggiunge n il ciclo termina sicuramente, cioè per
- 2m = n
- m = log2 n
quindi, nel caso pessimo: T(n) = 7 log2 n + 13, quindi
Confronto
Il numero di accessi è molto diverso
- Ricerca sequenziale, mediamente:
, nel caso pessimo
- Ricerca binaria, nel caso pessimo:
L’algoritmo di ricerca binaria ha un codice più lungo, utilizza più variabili locali, richiede un’addizione e una divisione… ipotizziamo che le costanti della sua complessità in tempo siano molto alte, per esempio 10, 20, … contrapposte a 5 e 10
Confrontiamo i valori delle due funzioni al variare di n
n | Tseq(n) | Tbin(n) | |||
---|---|---|---|---|---|
4 | = 22 | 5·4+10 | = 30 | 10·2+20 | = 40 |
8 | = 23 | 5·8+10 | = 50 | 10·3+20 | = 50 |
16 | = 24 | 5·16+10 | = 90 | 10·4+20 | = 60 |
32 | = 25 | 5·32+10 | = 170 | 10·5+20 | = 70 |
64 | = 26 | 5·64+10 | = 330 | 10·6+20 | = 80 |
128 | = 27 | 5·128+10 | = 650 | 10·7+20 | = 90 |
256 | = 28 | 5·256+10 | = 1.290 | 10·8+20 | = 100 |
512 | = 29 | 5·512+10 | = 2.570 | 10·9+20 | = 110 |
1.024 | = 210 | 5·1.024+10 | = 5.130 | 10·10+20 | = 120 |
1.048.576 | = 220 | … | > 5*10^6 | 10·20+20 | = 220 |
1.073.741.824 | = 230 | … | > 5*10^9 | 10·30+20 | = 320 |
L’algoritmo di ricerca binaria (con strutture dati ordinate)
- è più efficiente già con 16 elementi
- e al crescere di n diventa irrinunciabile.