Elementi di complessità Complessità di un algoritmo Esempio: insertion sort Considerazioni Notazione asintotica
Complessità di un algoritmo In genere, la complessità di un algoritmo si valuta a seconda del tempo di esecuzione e dello spazio di memoria occupato durante la sua esecuzione. Tempo di esecuzione: si vuole dare una stima del tempo necessario per eseguire l’algoritmo, dal suo inizio fino al suo temine. Molto spesso si cerca di definire questo a seconda della dimensione dell’input. Spazio di memoria : si vuole dare una stima della memoria necessaria per eseguire l’algoritmo, dal suo inizio fino al suo temine. Informalmente, tutte le variabili utilizzate durante l’algoritmo contribuiscono ad aumentare la quantità di memoria che deve essere allocata.
Esempio di calcolo del tempo di esecuzione Si vuole associare ad ogni istruzione un tempo di esecuzione dato il modello computazionale. Ad ogni ciclo for key INSERTION-SORT(A) for j ← 2 to lenght[A] do key ← A[j] i ← j-1 while (i>0) and (A[i]>key) do A[i+1] ← A[i] i← i-1 A[i+1] ← key 1 2 3 4 3 9 8 7 1 2 3 4 3 9 8 7 1 2 3 4 3 8 9 7 Si vuole che il vettore A[1,…,n] sia ordinato in ordine crescente, ossia A[1]≤ A[2]≤ … ≤ A[n] 1 2 3 4 3 7 8 9
Esempio di calcolo del tempo di esecuzione Analisi: Volte eseguite INSERTION-SORT(A) for j ← 2 to lenght[A] do key ← A[j] i ← j-1 while (i>0) and (A[i]>key) do A[i+1] ← A[i] i← i-1 A[i+1] ← key Costo c1 c2 c3 c4 c5 c6 c7 tj dipende dal numero di volte che il controllo per eseguire ciclo while viene fatto ad ogni ciclo for (j). Si ha 1 ≤ tj ≤ i o anche 1 ≤ tj ≤ j-1.
Esempio di calcolo del tempo di esecuzione Supponiamo che c1=c2=…=c7=c=1. Possiamo calcolare il tempo complessivo dell’algoritmo: Nel caso migliore (BEST CASE) si ha tj=1 per ogni ciclo while. Nel caso peggiore (WORST CASE) si ha tj=j per ogni ciclo while.
Esempio di calcolo del tempo di esecuzione Alcune considerazioni: Il tempo di complessità nel caso peggiore ci dà una garanzia del tempo massimo di esecuzione dell’algoritmo. Spesso succede che il caso medio ha un comportamento simile a quello del caso peggiore. Nel nostro caso si ha infatti: Il calcolo del tempo nel caso medio risulta spesso più complesso del caso peggiore.
Quando un algoritmo ha una buona complessità? Quando il tempo di complessità è polinomiale. Quando il tempo di complessità è limitata da una funzione polinomiale. Ecco una motivazione pratica: n n logn n2 n3 2n 1 ms 1000 dati 140 31 10 9 1 sec 106 62.746 dati 1000 dati 100 19 1 ora 3,6x 109 dati 1,6X 108 dati 60.000 dati 1532 dati Si suppone che in 1 ms si riesca ad eseguire 1000 operazioni (istruzioni).
Notazione asintotica Θ c2 g(n) f(n) f(n) cresce asintoticamente come g(n)! Esempio: c1 g(n) n0
Notazione asintotica О c g(n) f(n) f(n) cresce asintoticamente come non più di g(n)! Esempio: n0
Notazione asintotica Ω f(n) f(n) cresce asintoticamente come almeno quanto g(n)! Esempio: c g(n) n0
Alcune proprietà Proprietà transitiva Proprietà riflessiva Proprietà simmetrica Proprietà antisimmetrica