Ordinamento dell’array 1 2 3 4 5 6 7 8 9 10 11 12 8 2 2 9 6 3 1 8 1 7 6 3 7 3 7 1 1 7 9 8 2 7 5 4 3 6 1 5 3 1 6 3 5 4 3 3 4 3 2 7 3 1 4 1 2 6 2 1 2 1 9 1 8 7 2 3 5 7 4 4 5 6 7 4 3 6 1 2 8 9 10 11 12
Max-Heapfy(A,i) l = 2i, r =2i+1 m = i if l A.heapsize and A[l] > A[m] m = l if r A.heapsize and A[r] > A[m] m = r if m i t = A[i], A[i] = A[m], A[m] = t Max-Heapfy(A,m)
Build-Max-Heap (A) A.heapsize = A.length for i = A.lenght/2 downto 1 Max-Heapfy(A,i)
Heap-Sort (A) Build-Max-Heap(A) for i = A.length downto 2 t = A[i], A[i] = A[1], A[1] = t A.heapsize = A.heapsize - 1 Max-Heapfy(A,1)
Paragonare tra loro algoritmi Abbiamo una scala di complessità: vogliamo inserire ogni algoritmo in questa scala
Un algoritmo può richiedere tempi diversi per input della stessa taglia. Ad esempio il tempo per ordinare n oggetti può dipendere dal loro ordine iniziale. complessità massima complessità media complessità minima
Nell’analizzare la complessità tempo di un algoritmo siamo interessati a come aumenta il tempo al crescere della taglia n dell’input. Siccome per valori “piccoli” di n il tempo richiesto è comunque poco, ci interessa soprattutto il comportamento per valori “grandi” di n (il comportamento asintotico)
Inoltre, siccome la velocità del processore influisce sul tempo calcolo per una costante moltiplicativa noi valuteremo la complessità a meno di una tale costante. Questo giustifica le seguenti definizioni:
Notazione asintotica O (limite superiore asintotico) O(g(n))
Scriveremo f(n) = O(g(n)) per dire che f(n) è una delle funzioni dell’insieme O(g(n)) si legge: f(n) è “o grande” di g(n) Se f(n) = O(g(n)) rappresenta il tempo calcolo richiesto da un algoritmo diciamo che O(g(n)) è un limite superiore asintotico per la complessità tempo di tale algoritmo.
esempi infatti per c = 4 ed n0 = 5 Vedremo che in generale per a2 > 0 a_2n^2+a_1n+a_0 \leq cn^2 a_2+a_1/n+a_0/n^2 \leq c c=2a_2 a_1/n+a_0/n^2 \leq a_2 a_1/n+a_0/n^2 \leq (|a_1|+|a_0|)/n \leq a_2 Vero per n \geq (|a_1|+|a_0|)/a_2 infatti per c = 3 ed n0 = 1
Notazione asintotica . (limite inferiore asintotico)
Scriveremo f(n) = (g(n)) per dire che f(n) è una delle funzioni dell’insieme (g(n)). si legge: f(n) è “omega” di g(n) Se f(n) = (g(n)) rappresenta il tempo calcolo richiesto da un algoritmo diciamo che (g(n)) è un limite inferiore asintotico per la complessità tempo di tale algoritmo.
esempi infatti per c = 1 ed n0 = 10 Vedremo che in generale se a2 > 0 a_2n^2+a_1n+a_0 \geq cn^2 a_2+a_1/n+a_0/n^2 \geq c c=a_2/2 a_2/2 \geq -a_1/n-a_0/n^2 -a_1/n-a_0/n^2 \leq (|a_1|+|a_0|)/n \leq a_2/2 Vero per n \geq 2(|a_1|+|a_0|)/a_2 infatti per c = 1 ed n0 = 1
Notazione asintotica . (limite asintotico stretto)
Scriveremo f(n) = (g(n)) per dire che f(n) è una delle funzioni dell’insieme (g(n)). si legge: f(n) è “theta” di g(n) Se f(n) = (g(n)) rappresenta il tempo calcolo richiesto da un algoritmo diciamo che (g(n)) è un limite asintotico stretto per la complessità tempo di tale algoritmo.
esempi Dunque per c1 = 1, c2 = 4 ed n0 = 10 Dunque
per ogni n n0 allora altrimenti per ogni n n0. Assurdo! per ogni n n0 allora altrimenti per ogni n n0. Assurdo!
Metodo del limite Spesso è possibile determinare dei limiti asintotici calcolando il limite di un rapporto. Ad esempio se allora per ogni > 0 esiste n0 tale che per n ≥ n0 Preso 0 < < k e posto c1 = k e c2 = k + e quindi
Se diciamo che ed in questo caso Se diciamo che ed in questo caso Attenzione: quando il limite del rapporto non esiste questo metodo non si può usare.
In generale per ogni funzione polinomiale di grado k con coefficiente ak > 0. Inoltre
Per 0 < h < k e 1 < a < b :
Valutare la difficoltà dei problemi esiste un algoritmo che risolve il problema con questa complessità limite superiore: O(n2)
Un limite superiore per il problema dell’ordinamento Abbiamo visto che Insert-Sort per ordinare n oggetti richiede O(n2) operazioni Quindi O(n2) è un limite superiore
Valutare la difficoltà dei problemi ogni algoritmo che risolve il problema ha complessità maggiore o uguale di questa limite inferiore: (n)