Algoritmi e Strutture Dati
Capitolo 4
Ordinamento: lower bound Ω(n log n) e
MergeSort ((*) l’intera lezione)
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Stato dell’arte
Caso Caso T(n)
Caso
migliore medio peggiore
S(n)
Selection Sort
Θ(n2)
Θ(n2)
Θ(n2)
Θ(n2)
Θ(n)
Insertion Sort 1
Θ(n2)
Θ(n2)
Θ(n2)
Θ(n2)
Θ(n)
Insertion Sort 2
Θ(n)
Θ(n2)
Θ(n2)
O(n2)
Θ(n)
Insertion Sort 3 Θ(n log n) Θ(n2)
Θ(n2)
O(n2)
Θ(n)
Bubble-Sort
Θ(n2)
Θ(n2)
Θ(n)
Θ(n2)
Θ(n2)
Nota: il Bubble-Sort può essere facilmente modificato in
modo tale che il caso migliore costi Θ(n). Come?
2
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Quindi, per il problema dell’ordinamento…
• Lower bound temporale: (n)
– “banale”: dimensione dell’input
• Upper bound temporale: O(n2)
– Insertion Sort 2 e 3
Abbiamo un gap lineare tra upper bound e lower bound!
È possibile chiudere tale gap?
3
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Ordinamento per confronti
Dati due elementi ai ed aj, per determinarne l’ordinamento relativo
effettuiamo una delle seguenti operazioni di confronto:
a i  aj ; ai  aj ; a i  aj ; ai  aj ; ai  aj
Non si possono esaminare i valori degli elementi o ottenere
informazioni sul loro ordine in altro modo.
Notare: Tutti gli algoritmi di ordinamento considerati fino ad
ora sono algoritmi di ordinamento per confronto.
4
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Lower bound (n log n) per l’ordinamento
• Consideriamo un generico algoritmo A, che ordina
eseguendo solo confronti: dimostreremo che A esegue (nel
caso peggiore) (n log n) confronti
• Un generico algoritmo di ordinamento per confronti lavora
nel modo seguente:
- Confronta due elementi ai ed aj (ad esempio effettua il test ai  aj);
- A seconda del risultato, riordina e/o decide il confronto
successivo da eseguire.
 Un algoritmo di ordinamento per confronti può essere
descritto in modo astratto usando un albero di decisione,
nel quale i nodi interni rappresentano i confronti, mentre le
foglie rappresentano gli output prodotti
5
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Albero di decisione
• Un albero di decisione è associato ad uno specifico
algoritmo A e ad una specifica dimensione n
dell’istanza
• Descrive le diverse sequenze di confronti che A esegue
su un’istanza <a1,a2,…,an> di lunghezza n; i movimenti
dei dati e tutti gli altri aspetti dell’algoritmo vengono
ignorati
• Nodo interno (non foglia): i:j (modella il confronto
tra ai e aj)
• Nodo foglia: i1,i2,…,in (modella una risposta (output)
dell’algoritmo, ovvero una permutazione <ai1,ai2,…,ain>
degli elementi)
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio
Input <a1,a2,a3>
Š
1,2,3
1:2
Š
2:3
Š
1,3,2
Š

1:3


3,1,2
2,1,3
1:3
Š
2,3,1
Riconoscete
l’algoritmo
associato?

2:3

3,2,1
È proprio l’Insertion Sort 2 su una sequenza di 3
elementi!
Approfondimento: costruire l’albero di decisione per
il SS (e per il BS) su una sequenza di 3 elementi.
7
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Proprietà
• Per una particolare istanza, i confronti eseguiti da
A su quella istanza rappresentano un cammino
radice – foglia
• L’algoritmo segue un cammino diverso a seconda
delle caratteristiche dell’input
– Caso peggiore: cammino più lungo
– Caso migliore: cammino più breve
• Il numero di confronti nel caso peggiore è pari
all’altezza dell’albero di decisione (ovvero alla
lunghezza, in termini di numero di archi, del più
lungo cammino radice-foglia)
8
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Altezza in funzione delle foglie
Lemma: Un albero binario (ovvero, in cui ogni nodo interno
ha al più due figli) con k foglie ha altezza h(k)  log2 k.
Dim: Dimostrazione per induzione sul numero di foglie k:
– Caso base k=1: banale, perché ogni albero con una foglia deve
avere almeno altezza log21=0 (anche nel caso limite dell’albero
costituito da un unico nodo )
– Caso k>1: supposto vero per k-1 foglie, dimostriamolo per k;
poiché la radice ha almeno un figlio, uno dei suoi al più due
sottoalberi deve contenere almeno la metà (parte intera superiore)
delle foglie, e quindi
h(k) ≥1+h(k/2) ≥ (hp induttiva) 1+log2(k/2)
=1+log2k-log22=log2k.
QED
9
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Il lower bound (n logn)
• Consideriamo l’albero binario di decisione di un qualsiasi
algoritmo che risolve il problema dell’ordinamento di n elementi
• Tale albero deve avere almeno n! foglie: infatti, se l’algoritmo è
corretto, deve contemplare tutti i possibili output, ovvero le n!
permutazioni della sequenza di n elementi in input
• Dal lemma precedente, avremo che l’altezza h(n) dell’albero di
decisione sarà:
h(n)  log2(#foglie)  log2(n!) > log2 (n/e)n =
Formula di Stirling:
n!  (2pn)1/2 ·(n/e)n
> (n/e)n
10
= n log2 (n/e) =
= n log2 n – n log2 e =
= (n log n)
QED
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Un algoritmo ottimo: il MergeSort
(John von Neumann, 1945)
• Problema dell’ordinamento:
– Lower bound - (n log n) albero di decisione
– Upper bound – O(n2)
IS 2 e 3
• Abbiamo ridotto il gap tra LB e UB da Θ(n) a Θ(n/log
n); proviamo a costruire un algoritmo ottimo (cioè a
ridurre il gap a Θ(1)) usando la tecnica del divide et
impera:
1 Divide: dividi l’array a metà
2 Risolvi il sottoproblema ricorsivamente
3 Impera: fondi le due sottosequenze ordinate
11
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio di esecuzione
12
7 2 4 5 3 1 5 6
input
1 2 3 4 5 5 6 7
output
7 2 4 5
3 1 5 6
2 4 5 7
1 3 5 6
7 2
4 5
3 1
5 6
2 7
4 5
1 3
5 6
Input ed
output delle
chiamate
ricorsive
7
2
4
5
3
1
5
6
7
2
4
5
3
1
5
6
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Fusione di sequenze ordinate
• Due array ordinati A e B possono essere fusi
rapidamente:
– estrai ripetutamente il minimo di A e B e copialo
nell’array di output, finché A oppure B non
diventa vuoto
– copia gli elementi dell’array non ancora
completamente svuotato alla fine dell’array di
output
Notazione: dato un array A e due indici x  y, denotiamo con
A[x;y] la porzione di A costituita da A[x], A[x+1],…,A[y]
13
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Algoritmo di fusione di sequenze ordinate
Merge (A, i1, f1, f2)
1.
Sia X un array ausiliario di lunghezza f2-i1+1
2.
i=1
3.
i2=f1+1
4.
while (i1 f1 e i2  f2) do
5.
if (A[i1]  A[i2])
6.
then X[i]=A[i1]
7.
8.
9.
incrementa i e i1
Osservazione: usa
l’array ausiliario X
else X[i]=A[i2]
incrementa i e i2
10.
if (i1<f1) then copia A[i1;f1] alla fine di X
11.
else copia A[i2;f2] alla fine di X
12.
copia X in A[i1;f2]
14
fonde A[i1;f1] e A[f1+1;f2]
output in A[i1;f2]
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Costo dell’algoritmo di merge
Lemma
La procedure Merge fonde due sequenze ordinate di
lunghezza n1 e n2 eseguendo al più n1+ n2 -1 confronti
Dim: Ogni confronto “consuma” un elemento di A.
Nel caso peggiore tutti gli elementi tranne l’ultimo sono
aggiunti alla sequenza X tramite un confronto.
Il numero totale di elementi è n1+ n2. Quindi il numero totale
di confronti è n1+ n2 -1.
QED
Numero di confronti: C(n=n1+ n2)=O(n1+ n2)=O(n)
(si noti che vale anche C(n)=Ω(min{n1,n2}))
Numero di operazioni (confronti + copie)? T(n)=(n1+ n2)
15
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
MergeSort
MergeSort (A, i, f)
1.
if (i  f) then return
2.
m = (i+f)/2
3.
MergeSort(A,i,m)
4.
MergeSort(A,m+1,f)
5.
Merge(A,i,m,f)
16
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Tempo di esecuzione
• Il numero di confronti del MergeSort è descritto dalla seguente
relazione di ricorrenza:
C(n) ≤ 2 C(n/2) + Θ(n)
C(1)=0
(si noti che f(n)=Θ(n), in quanto il numero di confronti nelle fusioni è
ovviamente C(n)=O(n), ma anche C(n)=Ω(min{n1,n2})=Ω(min{n/2,
n/2})=Ω(n))
• Usando il caso 2 del Teorema Master (infatti a=b=2, e quindi
f(n)Θ(n)=Θ(nlog22)Θ(nlogba)), si ottiene
C(n) = O(nlog22 log n) = O(n log n)
(si noti che utilizzo la notazione O in quanto nella relazione di
ricorrenza compare il simbolo ≤)
• Infine, per il tempo di esecuzione totale (confronti + copie), si ha:
T(n) = 2 T(n/2) + Θ(n) T(1)=1  T(n) = Θ(n log n)
(si noti che in questo caso utilizzo la notazione Θ in quanto nella
relazione di ricorrenza compare il simbolo =)
17
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Più precisamente…
1. Nel caso peggiore, il MS esegue (n ⌈log n⌉ - 2⌈log n⌉ +
1) confronti, che corrisponde ad un numero compreso
tra (n log n - n + 1) e (n log n + n + O(log n))
2. Nel caso medio, il MS esegue (n ⌈log n⌉ - 2⌈log n⌉ + 1)
– 0.2645·n confronti
3. Nel caso migliore (array già ordinato), il MS esegue
n-1 confronti; in tal caso, se migliorassimo la
procedura di Merge facendo un controllo
preliminare tra ultimo elemento della prima sequenza
e primo della seconda prima ancora di allocare
memoria aggiuntiva, otterremmo tempo e spazio
lineare, cioè Θ(n).
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Osservazioni finali
• Problema dell’ordinamento: abbiamo chiuso il gap!
– Lower bound - (n log n) albero di decisione
– Upper bound – Θ(n log n) Merge Sort
• Il MergeSort è dunque un algoritmo
(asintoticamente) ottimo rispetto al numero di
confronti eseguiti nel caso peggiore
• Il MergeSort non ordina in loco, e utilizza
memoria ausiliaria (l’occupazione di memoria
finale è pari a Θ(n log n))
19
Copyright © 2004 - The McGraw - Hill Companies, srl