Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Algoritmi e Strutture Dati
Capitolo 1
Un’introduzione informale
agli algoritmi:
ancora sulla sequenza di Fibonacci
1
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Punto della situazione
• Stiamo cercando di calcolare efficientemente l’nesimo numero della sequenza di Fibonacci
• Abbiamo progettato 3 algoritmi:
– fibonacci1, non corretto in quanto approssima la
soluzione
– fibonacci2, che impiega tempo esponenziale in n
– fibonacci3, che impiega tempo proporzionale ad n
• Dovevamo dimostrare che per fibonacci2(n)
T(n) = Fn + 2 (Fn-1) = 3Fn-2
# Foglie
2
# Nodi interni
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Occupazione di memoria
• Il tempo di esecuzione non è la sola risorsa di calcolo
che ci interessa. Anche la quantità di memoria necessaria
può essere cruciale.
• Se abbiamo un algoritmo lento, dovremo solo attendere
più a lungo per ottenere il risultato
• Ma se un algoritmo richiede più spazio di quello a
disposizione, non otterremo mai la soluzione,
indipendentemente da quanto attendiamo!
• È il caso di Fibonacci3, la cui correttezza è
subordinata alla dimensione della memoria allocabile
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Algoritmo fibonacci4
• fibonacci3 usa un array di dimensione n prefissata
• In realtà non ci serve mantenere tutti i valori di Fn
precedenti, ma solo gli ultimi due, riducendo lo spazio a
poche variabili in tutto:
algoritmo fibonacci4(intero n)  intero
ab1
for i = 3 to n do
c  a+b
ab
bc
return b
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Correttezza? Corretto per definizione!
Efficienza?
• Per la risorsa tempo, calcoliamo il numero di linee di
codice T(n) mandate in esecuzione
– Se n≤2: tre sole linee di codice
– Se n3: T(n) = 2+(n-1)+3·(n-2) = 4n-5 (per
Fibonacci3 avevamo T(n)=2n)
• Per la risorsa spazio, contiamo il numero di variabili
di lavoro utilizzate: S(n)=4 (per Fibonacci3
avevamo S(n)=n+1) [NOTA: stiamo assumendo che
ogni locazione di memoria può contenere un valore
infinitamente grande!]
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Notazione asintotica
• Misurare T(n) come il numero di linee di
codice mandate in esecuzione è una misura
molto approssimativa del tempo di
esecuzione
• Se andiamo a capo più spesso, aumenteranno
le linee di codice sorgente, ma certo non il
tempo richiesto dall’esecuzione del
programma!
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Notazione asintotica
• Per lo stesso programma impaginato diversamente
potremmo concludere ad esempio che T(n)=3n
oppure T(n)=5n
• Vorremmo un modo per descrivere l’ordine di
grandezza di T(n) ignorando dettagli inessenziali
come le costanti moltiplicative, additive e
sottrattive
• Useremo a questo scopo la notazione asintotica Θ
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Notazione asintotica Q (definizione
informale)
Supponiamo che
lim
n 
f ( n)
 L, 0  L  
g ( n)
Allora, scriveremo che f(n) = Q(g(n)).
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempi:
Sia f(n) = 2n2 + 3n, allora f(n)=Θ(n2)
Sia f(n) = n2 – n log n, allora f(n)=Θ(n2)
Sia f(n) = n3 -2n2+3n, allora f(n)=Θ(n3)
Sia f(n) = 23, allora f(n)=Θ(1)
Sia f(n) = 3n +2n, allora f(n)=Θ(3n)
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Andamento asintotico per i Fibonacci
• Fibonacci2 T(n)=3Fn-2  T(n)=Θ(Fn) 
T(n)=Θ(n), poiché
1
lim
n 


5
n
n
n


 1
5
• Fibonacci3 T(n)=2n  T(n)=Θ(n)
• Fibonacci4 T(n)=4n-5  T(n)=Θ(n)
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Un nuovo algoritmo
Possiamo sperare di calcolare Fn in tempo
inferiore a Θ(n)?
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Potenze ricorsive
• Fibonacci4 non è il miglior algoritmo
possibile
• È possibile dimostrare per induzione la seguente
proprietà di matrici:
1 1
1 0
n
=
Fn+1 Fn
Fn Fn-1
• Useremo questa proprietà per progettare un
algoritmo più efficiente
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…prodotto di matrici
 a1,1  a1,n 


A    

a
 n ,1  an ,n 
 b1,1  b1,n 


B    
b


b
n,n 
 n ,1
n
(AB)i,j= k=1
 ai,k bk,j
i=1,…, n
j=1,…, n
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Dimostrazione per induzione
Base induzione: n=2
2
1 1
1 0
= 1 1  1 1 = 2 1 = F3 F2
1 0
1 0
1 1
F2 F1
1 1
Hp induttiva:
1 0
n

n-1
=
Fn Fn-1
Fn-1 Fn-2
1 1 = Fn Fn-1  1 1
Fn + Fn-1 Fn
Fn+1 Fn
=
1 0
Fn-1 Fn-2
1 0
Fn-1+ Fn-2 Fn-1 = Fn Fn-1

Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Algoritmo fibonacci5
• Osserva che il ciclo arriva fino ad n-1
• Il tempo di esecuzione è T(n)=2+n+n-1 = Θ(n)
• Possiamo migliorare?
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Calcolo di potenze
• Possiamo calcolare la n-esima potenza elevando al
quadrato la n/2 - esima potenza
• Se n è dispari eseguiamo una ulteriore moltiplicazione
• Esempio: se devo calcolare 38:
38 = (34)2 = [(32)2]2 = [(3·3)2]2 = [(9)2]2 = [(9·9)]2 = [81]2
= 81·81 = 6561
 Ho eseguito solo 3 prodotti invece di 8
• Esempio: se devo calcolare 37:
37 = 3·(33)2 = 3·(3·(3)2)2 = 3·(3·(3·3))2 = 3·(3·9)2 =
3·(27)2 = 3·(27·27) = 3·(729) = 2187
 Ho eseguito solo 4 prodotti invece di 7
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Algoritmo fibonacci6
passaggio
per valore
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Tempo di esecuzione
• Tutto il tempo è speso nella procedura
potenzaDiMatrice
– All’interno della procedura si spende tempo costante
– Si esegue una chiamata ricorsiva con input n/2
• L’equazione di ricorrenza è pertanto:
T(n) = T(n/2) + Θ(1)
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Metodo dell’iterazione
Si può dimostrare che
T(n) = Θ(log2 n )
Infatti: T(n)=T(n/2)+Θ(1)=(T( n/22)+Θ(1))+Θ(1)=
=((T(n/23)+Θ(1))+Θ(1))+Θ(1)=…
e per k = log2 n si ha n/2k = 1 e quindi
T(n)=((…(T(n/2k)+Θ(1))+…+Θ(1))+Θ(1))+Θ(1)
= T(1)+k∙Θ(1) = Θ(1) + log2 n∙Θ(1) = Θ(log n)
fibonacci6 è quindi esponenzialmente più
veloce di fibonacci5!
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Riepilogo
Numero di linee di
codice
Occupazione di
memoria
fibonacci1
Θ(1)
Θ(1)
fibonacci2
Θ(n)
Θ(n)
fibonacci3
Θ(n)
Θ(n)
fibonacci4
Θ(n)
Θ(1)
fibonacci5
Θ(n)
Θ(1)
fibonacci6
Θ(log n)
Θ(log n)*
* Θ(log n) per le variabili di lavoro e Θ(log n) per le chiamate ricorsive
Copyright © 2004 - The McGraw - Hill Companies, srl