Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Ordinamenti ottimi
(nel modello basato su confronti)
1
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
MergeSort
• Usa 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
2
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio di esecuzione
3
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
Procedura Merge
• 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 vuoto 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]
4
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
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
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]
5
fonde A[i1;f1] e A[f1+1;f2]
output in A[i1;f2]
Osservazione: sto
usando un array
ausiliario
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
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.
numero di confronti nel caso peggiore è (n1+ n2)
Il numero di operazioni (confronti + copie)? (n1+ n2)
6
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
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)
7
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) + O(n)
• Usando il Teorema Master si ottiene
C(n) = O(n log n)
a=b=2, f(n)=O(n)  caso 2
8
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…alcune osservazioni…
• Il MergeSort è un algoritmo (asintoticamente)
ottimo rispetto al numero di confronti eseguiti nel
caso peggiore
• Il MergeSort non ordina in loco
– occupazione di memoria pari a 2n
9
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
HeapSort
• Stesso approccio incrementale del selectionSort
– seleziona gli elementi dal più grande al più piccolo
– usa una struttura dati efficiente
• estrazione in tempo O(log n) del massimo
• Tipo di dato
– Specifica delle operazioni di interesse su una collezione di oggetti (es.
inserisci, cancella, cerca)
• Struttura dati
– Organizzazione dei dati che permette di supportare le operazioni di un
tipo di dato usando meno risorse di calcolo possibile
• Cruciale: progettare una struttura dati H su cui eseguire
efficientemente le operazioni:
– dato un array A, generare velocemente H
– trovare il più grande oggetto in H
– cancellare il più grande oggetto da H
10
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Alberi: qualche altra definizione
albero d-ario: albero in cui tutti i nodi interni hanno d figli
d=2  albero binario
un albero d-ario è completo se tutte le foglie sono allo
stesso livello
11
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
HeapSort
• Struttura dati heap associata ad un insieme S =
albero binario radicato con le seguenti proprietà:
1) completo fino al penultimo livello (foglie
sull’ultimo livello tutte compattate a sinistra)
2) gli elementi di S sono memorizzati nei nodi
dell’albero
3) chiave(padre(v)) ≥ chiave(v) per ogni nodo v
12
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…un esempio
16
10
14
In questa
direzione è
presente un
ordinamento
7
8
2
4
9
3
il massimo è
contenuto
nella radice!
1
In questa direzione non è
presente un ordinamento
13
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Struttura dati heap
Rappresentazione con vettore posizionale
sin(i) = 2i
des(i) = 2i+1
padre(i)=i/2
37
22
31
13
7
15
12
3
25
14
è sufficiente un vettore di
dimensione n
9
vettore posizionale
0
37 22 31 13 15 25 14
7
3 12
1
8
9
2
3
4
5
6
7
9
10 11
in generale
dimensione vettore
diverso da numero
elementi
nello pseudocodice numero oggetti
indicato con heapsize[A]
14
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Proprietà salienti degli heap
1) Il massimo è contenuto nella radice
2) L’albero ha altezza O(log n)
3) Gli heap con struttura rafforzata possono essere
rappresentati in un array di dimensione pari a n
15
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
La procedura fixHeap
Se tutti i nodi di H tranne v soddisfano la proprietà di
ordinamento a heap, possiamo ripristinarla come segue:
fixHeap(nodo v, heap H)
if (v è una foglia) then return
else
sia u il figlio di v con chiave massima
if ( chiave(v) < chiave(u) ) then
scambia chiave(v) e chiave(u)
fixHeap(u,H)
Tempo di esecuzione: O(log n)
16
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
i=1
FixHeap - esempio
16
2
3
4
10
4
5
14
7
8
9
10
2
8
1
6
9
3
16
2
3
14
10
4
5
8
7
8
9
10
2
4
1
17
i=1
7
6
9
16
2
3
14
10
4
5
4
7
8
9
10
2
8
1
6
9
7
3
Copyright © 2004 - The McGraw - Hill Companies, srl
7
3
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…uno pseudocodice di fixHeap più dettagliato…
fixHeap (i,A)
1.
s=sin(i)
2.
d=des(i)
3.
if (s  heapsize[A] e A[s] >A[i])
4.
then massimo=s
5.
else massimo=i
6.
if (d  heapsize[A] e A[d] >A[massimo])
7.
then massimo=d
8.
if (massimoi)
9.
then scambia A[i] e A[massimo]
10.
18
fixHeap(massimo,A)
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Estrazione del massimo
• Copia nella radice la chiave contenuta nella la
foglia più a destra dell’ultimo livello
– nota: è l’elemento in posizione n (n: dimensione heap)
• Rimuovi la foglia
• Ripristina la proprietà di ordinamento a heap
richiamando fixHeap sulla radice
Tempo di esecuzione: O(log n)
19
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Costruzione dell’heap
Algoritmo ricorsivo basato sul divide et impera
heapify(heap H)
if (H è vuoto) then return
else
heapify(sottoalbero sinistro di H)
heapify(sottoalbero destro di H)
fixHeap(radice di H,H)
Tempo di esecuzione: T(n)= 2T(n/2)+O(log n)
T(n) = O(n)
20
dal Teorema Master
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…una versione iterativa di heapify…
heapify (A)
1.
Heapsize[A]=n
2.
for i=n/2 down to 1 do
3.
fixHeap(i,A)
Nota: gli elementi A[n/2+1],…,A[n] sono foglie dell’albero
T(n) 
T
FixHeap
nodi di
altezza 1
H
H
h 1
h 1
  N nodi h   TFixHeap h    N nodi h   Oh 
H = altezza albero  log2(n)
Nnodi(h) = numero di nodi di altezza h  n/2h+1 ( n/2h+1 )
n
n  h
T(n)  C   h 1  h  C    h  C  n  O(n)
2 h 1 2
h 1 2
log(n)
21
2
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
L’algoritmo HeapSort
• Costruisce un heap tramite heapify
• Estrae ripetutamente il massimo per n-1 volte
– ad ogni estrazione memorizza il massimo nella posizione
dell’array che si è appena liberata
22
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio di esecuzione
37
31
13
22
15
25
25
13
22
15
22
13
15
37 31 22 13 15 25
31 25 22 13 15 37
25 15 22 13 31 37
(1)
(2)
(3)
22
15
23
25
31
15
13
13
13
22 15 13 25 31 37
15 13 22 25 31 37
13 15 22 25 31 37
(4)
(5)
(6)
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
heapSort (A)
1.
Heapify(A)
2.
for i=n down to 2 do
3.
scambia A[1] e A[i]
4.
Heapsize[A] = Heapsize[A] -1
5.
fixHeap(1,A)
O(n)
n-1
estrazioni
di costo
O(log n)
ordina in loco in tempo O(n log n)
24
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
QuickSort
• Usa la tecnica del divide et impera:
1 Divide: scegli un elemento x della sequenza
(perno) e partiziona la sequenza in elementi
≤ x ed elementi >x
2 Risolvi i due sottoproblemi ricorsivamente
3 Impera: restituisci la concatenazione delle
due sottosequenze ordinate
Rispetto al MergeSort, divide complesso ed impera semplice
25
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
QuickSort (A)
1.
scegli elemento x in A
2.
partiziona A rispetto a x calcolando:
3.
A1={y  A : y  x}
4.
A2={y  A : y > x}
5.
if (|A1| > 1) then QuickSort(A1)
6.
if (|A2| > 1) then QuickSort(A2)
7.
copia la concatenazione di A1 e A2 in A
non partiziona in loco!
26
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Partizione in loco
• Scorri l’array “in parallelo” da sinistra verso
destra e da destra verso sinistra
– da sinistra verso destra, ci si ferma su un elemento
maggiore del perno
– da destra verso sinistra, ci si ferma su un elemento
minore del perno
• Scambia gli elementi e riprendi la scansione
27
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Partizione in loco: un esempio
28
45 12 93 3
67 43 85 29 24 92 63 3
21
45 12 21 3
67 43 85 29 24 92 63 3
93
45 12 21 3
3 43 85 29 24 92 63 67 93
45 12 21 3
3 43 24 29 85 92 63 67 93
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Partition (A, i, f )
1.
x=A[i]
2.
inf =i
3.
sup= f + 1
4.
while (true) do
partiziona A[i;f]
rispetto a A[i]
5.
do (inf=inf + 1) while (A[inf]  x)
6.
do (sup=sup-1) while (A[sup] > x)
7.
if (inf < sup) then scambia A[inf] e A[sup]
8.
else break
9.
scambia A[i] e A[sup]
10.
return sup
Tempo di
esecuzione:
O(n)
mette il perno “al centro”
Proprietà:
In ogni istante, gli elementi A[i],…,A[inf-1] sono  del perno,
mentre gli elementi A[sup+1],…,A[f] sono > del perno
29
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
QuickSort (A, i, f )
1.
if (i  f) then return
2.
m=Partition(A,i,f)
3.
QuickSort(A,i,m-1)
4.
QuickSort(A, m +1,f)
30
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
5 5 6 7 1 2 3 4
2 5 4 3 1 5 7 6
1 2 3 4 5 5 6 7
2 5 4 3 1
1 2 4 3 5
1 2 3 4 5
1
1
1
31
dopo partition
output
7 6
6 7
6 7
4 3 5
3 4 5
3 4 5
3
3
3
input
6
6
6
Esempio di
esecuzione
L’albero delle
chiamate
ricorsive può
essere
sbilanciato
5
5
5
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Analisi nel caso peggiore
• Nel caso peggiore, il perno scelto ad ogni passo è il
minimo o il massimo degli elementi nell’array
• Il numero di confronti è pertanto:
C(n)=C(n-1) + O(n)
• Svolgendo per iterazione si ottiene
C(n) = O(n2)
complessità nel caso migliore?
32
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Caso migliore: O(n log n), partizionamento sempre bilanciato
33
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…intuizioni sul caso medio…
• problema: la partizione può essere sbilanciata
• la probabilità che ad ogni passo si presenti la
partizione peggiore è molto bassa
• per partizioni che non sono “troppo sbilanciate”
l’algoritmo è veloce
• domanda: quale è la complessità dell’algoritmo
supponendo che l’algoritmo di partizionamento
produca sempre una partizione proporzionale 9-a-1
• Nota: sembra una partizione piuttosto sbilanciata…
34
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
…la complessità è ancora O(n log n)
35
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Randomizzazione
• Possiamo evitare il caso peggiore scegliendo
come perno un elemento a caso
• Poiché ogni elemento ha la stessa probabilità,
pari a 1/n, di essere scelto come perno, il
numero di confronti nel caso atteso è:
n-1
C(n)=

a=0
n-1
2 C(a)
1 n-1+C(a)+C(n-a-1) = n-1+

n
n
a=0
dove a e (n-a-1) sono le dimensioni dei sottoproblemi
risolti ricorsivamente
36
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Analisi nel caso medio
La relazione di ricorrenza del quicksort ha soluzione
C(n) ≤ 2 n log n
Dimostrazione per sostituzione integrando per parti
37
Copyright © 2004 - The McGraw - Hill Companies, srl