Tipici tempi di esecuzione
Martedì 7 ottobre 2014
Punto della situazione
• Abbiamo definito il tempo di esecuzione di un
algoritmo
• Scelto l’analisi asintotica
• Abbiamo definito le notazioni asintotiche che
ci permettono di confrontarlo con altri
algoritmi o con dei tempi «tipici» di
esecuzione: logaritmico, lineare, polinomiale,
etc….
• Perché queste funzioni sono «tempi tipici di
esecuzione»?
Tempo di esecuzione
Tempo di esecuzione T(n) è il numero di operazioni
elementari per eseguire l’algoritmo su un input di taglia n
Sono operazioni elementari le operazioni che richiedono
tempo costante (= non dipendente dalla taglia n
dell’input)
Per esempio: assegnamento, incremento, confronto
Nelle prossime slides vedremo alcuni esempi tipici del
calcolo del tempo di esecuzione di algoritmi di tipo
iterativo (strutturati come for e while)
Esercizio (continua)
Esempio: InsertionSort
Algoritmo di ordinamento di A[1…n] ottenuto mantenendo ad
ogni iterazione A[1…j-1] ordinato e inserendovi A[j].
Analisi di InsertionSort
Più precisamente:
Fissato j, il test del while è eseguito un numero di volte fra 1 e j. Da cui
𝑛
𝑗=
T(n) ≤
𝑗=2
𝑛(𝑛+1)
2
Inoltre T(n) =  (n)
-1
e quindi T(n) = O (n2).
Linear Time: O(n)
Linear time. Running time is at most a
constant factor times the size of the input.
max  a1
for i = 2 to n {
if (ai > max)
max  ai
}
Computing the maximum. Compute
maximum of n numbers a1, …, an.
14
Linear Time: O(n)
Merge. Combine two sorted lists A = a1,a2,…,an with
b1,b2,…,bn
B =
into sorted whole.
i = 1, j = 1
while (both lists are nonempty) {
if (ai  bj) append ai to output list and increment i
else(ai > bj)append bj to output list and increment j
}
append remainder of nonempty list to output list
Claim. Merging two lists of size n takes O(n) time.
Pf. 15
After each comparison, the length of output list increases by 1.
Quadratic Time:
2
O(n )
Quadratic time. Enumerate all pairs of elements.
Closest pair of points. Given a list of n points in the plane
(x1, y1), …, (xn, yn), find the pair that is closest (here min is the
square of the minimum distance)
O(n2) solution. Try all pairs of points.
min  (x1 - x2)2 + (y1 - y2)2
for i = 1 to n {
for j = i+1 to n {
d  (xi - xj)2 + (yi - yj)2
if (d < min)
min  d
}
}
don't need to
take square roots
Remark. (n2) seems inevitable, but this is just an illusion.
16
Cubic Time:
3
O(n )
Cubic time. Enumerate all triples of elements.
Set disjointness. Given n sets S1, …, Sn each of which is a subset of
1, 2, …, n, is there some pair of these which are disjoint?
foreach set Si {
foreach other set Sj {
foreach element p of Si {
determine whether p also belongs to Sj
}
if (no element of Si belongs to Sj)
report that Si and Sj are disjoint
}
}
O(n3) solution. For each pairs of sets, determine if they are disjoint.
17
Polynomial Time: O(nk) Time
Independent set of size k. Given a graph, are there k nodes such that
no two are joined by an edge?
k is a constant
O(nk) solution. Enumerate all subsets of k nodes.
foreach subset S of k nodes {
check whether S in an
independent set
if (S is an independent set)
report S is an independent
set
}
}
18
Check whether S is an independent set = O(k2).
Number of k element subsets =
n  n (n 1) (n  2)
2
k
k
 
O(k n / k!) = O(n ).
k
 
(n  k 1)
nk

k (k 1) (k  2) (2) (1)
k!
Exponential Time
Independent set. Given a graph, what is maximum size
of an independent set?
O(n2 2n) solution. Enumerate all subsets.
S*  
foreach subset S of nodes {
check whether S in an independent set
if (S is largest independent set seen so far)
update S*  S
}
}
Note the differences with Independent set of size k.
19
Sub-linear Time: O(log n)
Tempo lineare: esamina tutto l’input eseguendo
operazioni di tempo costante ad ogni passo
Tempo sub-lineare: Non è necessario esaminare
tutto l’input!
Esempio. Ricerca binaria: ricerca di un elemento in
un array ordinato (per esempio un vocabolario)
20
O(n log n) Time
Molto comune perché
• E’ il running time di algoritmi divide-and-conquer che
dividono l’input in due parti, le risolvono ricorsivamente
e poi combinano le soluzioni in tempo lineare.
• Running time di algoritmi di ordinamento.
Mergesort e Heapsort usano O(n log n) confronti.
• Molti algoritmi usano l’ordinamento come passo più
costoso. Per esempio molti algoritmi basati sulla tecnica
greedy
23
Un esercizio
Algoritmi ricorsivi
• Riprendiamo l’esempio visto nel corso
di programmazione:
Il calcolo del fattoriale
Funzioni definite per ricorsione:
il fattoriale
Supponiamo di voler calcolare il fattoriale di n.
Partiamo dalla sua definizione:
n! n  (n  1)    3  2 1
… da cui otteniamo
una definizione del
(n  1)!
fattoriale in termini
di se stesso:
n! n  (n  1)!
se
n0
0! 1
Ricorsione - Ugo
de'Liguoro
Queste equazioni definiscono
anche un metodo per calcolare il
fattoriale
Un programma ricorsivo per il fattoriale
1
se n  0

n! 
n  (n  1)! se n  0
int fact (int n)
if (n==0) return 1
else return n * fact(n–1)
Chiamata ricorsiva: fact è
definito tramite se stesso
Ricorsione - Ugo
de'Liguoro
Come funziona il programma ricorsivo per il fattoriale?
Simuliamo il calcolo di fact(4) rimpiazzando più volte
fact(n) con la sua definizione:
fact(4)
4 * fact(3)
4 * (3 * fact(2))
4 * (3 * (2 * fact(1)))
4 * (3 * (2 * (1 * fact(0))))
4 * (3 * (2 * (1 * 1)))
4 * (3 * (2 * 1))
4 * (3 * 2)
4 * 6
24
Ricorsione - Ugo
de'Liguoro
Memento
• Ricordare che, durante l’esecuzione di
un algoritmo ricorsivo, non si può
procedere oltre una chiamata ricorsiva
se questa non è stata completata del
tutto.
Algoritmi ricorsivi
Schema di un algoritmo ricorsivo (su un’istanza I ):
ALGO (I )
If «caso base» then «esegui certe operazioni»
else «esegui delle operazioni fra le quali
ALGO(I 1), … , ALGO(I k) »
Per assicurare che la ricorsione termini bisogna fare attenzione a che le
chiamate ricorsive si applichino a valori di “dimensione” minore del
valore in ingresso, e che le clausole di uscita contemplino tutti i casi
base.
Ricorsione e iterazione
• La ricorsione è un metodo di calcolo basato sulla
possibilità che una funzione chiami se stessa
• L’iterazione può simulare una ricorsione qualsiasi
grazie all’uso di una pila
• La ricorsione è utile per scoprire un algoritmo, ma
anche per descriverlo in forma chiara e compatta
• Ove possibile si cerca poi di migliorare l’efficienza
dell’algoritmo, (eventualmente trasformandolo in
iterazione)
Ricorsione - Ugo
de'Liguoro
Cambio orario dal 6/10
• Martedì 9 - 11
• Mercoledì 13 – 15
• Martedì 14 test di valutazione sul
programma finora svolto