1 LEZIONE 19: Ordinamento (2) Informatica 3 Lezione 19

Informatica 3
Informatica 3
LEZIONE 19: Ordinamento (2)
Lezione 19 - Modulo 1
• Modulo 1: Mergesort
• Modulo 2: Heapsort, Binsort, Radix sort
• Modulo 2: Confronto tra algoritmi
Politecnico di Milano - Prof. Sara Comai
Mergesort
1
Politecnico di Milano - Prof. Sara Comai
Mergesort (1)
Mergesort (2)
• Algoritmo semplice e con buone prestazioni, difficile da
implementare
• Dividi et impera: suddivide la lista in due sotto-liste uguali, le
ordina e poi le ricombina
– Metodo complementare al Quicksort:
Implementazione:
List mergesort(List inlist) {
if (inlist.length() <= 1)return inlist;
List l1 = half of the items from inlist;
List l2 = other half of items from inlist;
return merge(mergesort(l1),
mergesort(l2));
}
• Quicksort: operazione di selezione del pivot + 2 chiamate
ricorsive
• Mergesort: 2 chiamate ricorsive + operazione di merging
• Il tempo di esecuzione non dipende dai valori iniziali
– nel caso peggiore ha prestazioni migliori del Quicksort
• Nel caso medio è meno efficiente di un fattore costante del
Quicksort
• Metodo stabile
• Svantaggio: richiede una quantità di memoria aggiuntiva
proporzionale al numero di elementi da ordinare
Politecnico di Milano - Prof. Sara Comai
2
Esempio:
3
Politecnico di Milano - Prof. Sara Comai
4
1
Mergesort (3)
Mergesort (3)
14
Politecnico di Milano - Prof. Sara Comai
5
Mergesort (3)
Politecnico di Milano - Prof. Sara Comai
6
Mergesort (3)
14 15
14 15 17...
Politecnico di Milano - Prof. Sara Comai
7
Politecnico di Milano - Prof. Sara Comai
8
2
Mergesort (4)
Mergesort (5)
• Difficoltà di implementazione
Implementazione:
– come rappresentare le liste
template <class Elem>
void mergesort(Elem A[], Elem temp[],
int left, int right) {
int mid = (left+right)/2;
if (left == right) return;
mergesort<Elem>(A, temp, left, mid);
mergesort<Elem>(A, temp, mid+1, right);
for (int i=left; i<=right; i++) // Copy
temp[i] = A[i];
int i1 = left; int i2 = mid + 1;
for (int curr=left; curr<=right; curr++) {
if (i1 == mid+1)
// Left exhausted
A[curr] = temp[i2++];
else if (i2 > right) // Right exhausted
A[curr] = temp[i1++];
else if (temp[i1] < temp[i2])
A[curr] = temp[i1++];
else A[curr] = temp[i2++];
}}
• liste concatenate (non occorre accesso diretto agli elementi,
ma sequenziale)
• array
– suddividere la lista in due metà
• lista concatenata
– prima metà e seconda metà: attraversamento di metà lista
concatenata
– assegnamento degli elementi in modo alternato alle due sotto-liste
• array: semplice se si conoscono gli estremi della lista
– merging di due array: utilizzando un secondo array
» il risultato è nel secondo array
» alternative: 1) si alternano i due array ad ogni passo; 2) si
copia il primo array nel secondo e si inserisce il risultato nel
primo
Politecnico di Milano - Prof. Sara Comai
9
Politecnico di Milano - Prof. Sara Comai
Mergesort (6)
Mergesort (7)
Implementazione ottimizzata:
• Prestazioni:
– utilizza insertion sort per ordinare liste di piccole dimensioni
– inverte l’ordine del secondo sotto-array durante la copia
iniziale
– parte di merging: Θ(i) con i = lunghezza totale dei
sotto-array da combinare
– profondità della ricorsione: log n per n elementi
template <class Elem>
void mergesort(Elem A[], Elem temp[],
int left, int right) {
if ((right-left) <= THRESHOLD) {
inssort<Elem>(&A[left],right-left+1);
return;
}
int i, j, k, mid = (left+right)/2;
if (left == right) return;
mergesort<Elem>(A, temp, left, mid);
mergesort<Elem>(A, temp, mid+1, right);
for (i=mid; i>=left; i--) temp[i] = A[i];
for (j=1; j<=right-mid; j++)
temp[right-j+1] = A[j+mid];
for (i=left,j=right,k=left; k<=right; k++)
if (temp[i] < temp[j]) A[k] = temp[i++];
else A[k] = temp[j--];
}
Politecnico di Milano - Prof. Sara Comai
10
• ad ogni livello della ricorsione:
– primo livello: 1 array di dimensione n
– secondo livello: 2 array di dimensione n/2
– terzo livello: 4 array di dimensione n/4 ...
−−> Θ(n)
• per tutti i livelli: Θ(n log n)
− Θ(n log n) nei casi migliore, peggiore e medio
11
Politecnico di Milano - Prof. Sara Comai
12
3
Heapsort (1)
Informatica 3
• Algoritmo di ordinamento basato su una
struttura ad albero
– bilanciato, efficiente dal punto di vista dello spazio
– tutti i valori da ordinare sono disponibili (non
vengono inseriti successivamente)
– si basa sulla struttura dati HEAP
– prestazioni: Θ(n log n) nei casi peggiore, migliore
e medio
– adatto quando l’insieme dei dati da ordinare è
elevato
Lezione 19 - Modulo 2
Heapsort, Binsort, Radix sort
Politecnico di Milano - Prof. Sara Comai
13
14
Politecnico di Milano - Prof. Sara Comai
Heapsort (2)
Heapsort (3)
• Algoritmo:
Implementazione:
– l’array viene trasformato in un max-heap
– passo 1: si rimuove il valore massimo dallo heap e
lo si inserisce in fondo all’array
– passo 2: si ricostruisce il max-heap
– si ripetono queste due operazioni fino a quando lo
heap è vuoto
template <class Elem>
void heapsort(Elem A[], int n) { // Heapsort
Elem mval;
maxheap<Elem> H(A, n, n);
for (int i=0; i<n; i++)
// Now sort
H.removemax(mval);
// Put max at end
}
Θ(n)
Θ(n log n)
Θ(n log n)
• Nel caso medio è più lento del Quicksort di un fattore costante
• Tempo per trovare l’elemento massimo nell’array: Θ(n + k log n)
Politecnico di Milano - Prof. Sara Comai
15
Politecnico di Milano - Prof. Sara Comai
16
4
Esempio (1)
Esempio (2)
array iniziale
rimuovi elemento 85
costruzione heap
rimuovi elemento 83
rimuovi elemento 88
Politecnico di Milano - Prof. Sara Comai
17
Politecnico di Milano - Prof. Sara Comai
Binsort (1)
Binsort (2)
• Estensioni:
– ammettere chiavi duplicate
• Algoritmo di base:
for (i=0; i<n; i++)
B[A[i]] = A[i];
A
0
4
5
3
1
2
18
A array di interi
0
1
2
3
4
5
• bin di lunghezza arbitraria: per ogni chiave uguale si inserisce
l’elemento in una lista
B
A
0
1
5
5
1
2
• i valori della chiave vengono utilizzati per assegnare i record ai
“bin”
• prestazioni: Θ(n) indipendentemente dai valori di input
• limite: lavora su una permutazione dei numeri da 0 a n-1
Politecnico di Milano - Prof. Sara Comai
19
B
0
1
2
3
4
5
Politecnico di Milano - Prof. Sara Comai
20
5
Binsort (2)
Binsort (3)
• Estensioni:
– ammettere chiavi duplicate
• Prestazioni:
– inserimento di ogni record nel giusto bin
– estrazione dei record dai bin
Æ Θ(n)
• bin di lunghezza arbitraria: per ogni chiave uguale si inserisce
l’elemento in una lista
– ammettere intervalli di valore maggiori di n
Implementazione:
– per ogni bin occorre vedere se contiene un record
– se MaxKeyValue > n (ad es. n2) allora l’estrazione
dei record dai bin richiede Θ(n2)
template <class Elem>
void binsort(Elem A[], int n) {
List<Elem> B[MaxKeyValue];
Elem item;
for (i=0; i<n; i++) B[A[i]].append(A[i]);
for (i=0; i<MaxKeyValue; i++)
for (B[i].setStart();
B[i].getValue(item); B[i].next())
output(item);
}
Politecnico di Milano - Prof. Sara Comai
21
Bucket sort
Politecnico di Milano - Prof. Sara Comai
22
Radix sort (1)
– Es. chiavi con valori [0,99]
• Generalizzazione del binsort
• assegnamento ai bin considerando il valore: chiave % 10
• ogni chiave viene assegnata al bin in base alla cifra
decimale più a destra
• i record ottenuti, nell’ordine, possono essere assegnati ai
bin in base alla cifra decimale di sinistra (chiave / 10)
• il risultato è ordinato
– ad ogni bin viene associato un intervallo di chiavi
– si ordinano le chiavi all’interno dei bin
– Gestione bucket non costosa se ogni bucket
contiene un numero limitato di elementi
Æ Radix sort (in base alla radice dei valori della chiave)
Politecnico di Milano - Prof. Sara Comai
23
Politecnico di Milano - Prof. Sara Comai
24
6
Radix Sort (2)
Radix Sort (3)
lista iniziale
Implementazione:
passo 2: cifra di sinistra
passo 1: cifra di destra
template <class Elem>
void radix(Elem A[], Elem B[],
int n, int k, int r, int cnt[]) {
// cnt[i] stores # of records in bin[i]
int j;
for (int i=0, rtok=1; i<k; i++, rtok*=r) {
for (j=0; j<r; j++) cnt[j] = 0;
// Count # of records for each bin
for(j=0; j<n; j++) cnt[(A[j]/rtok)%r]++;
// cnt[j] will be last slot of bin j.
for (j=1; j<r; j++)
cnt[j] = cnt[j-1] + cnt[j];
for (j=n-1; j>=0; j--)
B[--cnt[(A[j]/rtok)%r]] = A[j];
for (j=0; j<n; j++) A[j] = B[j];
}}
dopo il passo 1:
dopo il passo 2:
Politecnico di Milano - Prof. Sara Comai
25
Politecnico di Milano - Prof. Sara Comai
26
Radix sort (4)
Esempio
• Prestazioni:
input: array A
– k passi sulla lista di n numeri in base r:
• ad ogni passo: Θ(n+r)
• lavoro totale: Θ(nk+rk)
passo 1: rtok=1
– r può essere piccolo rispetto a n Æ costante
– k è il numero massimo di cifre di una chiave in base r: in
molte applicazioni Æ costante
array cnt: posizioni degli
indici per array B
fine passo 1: array A
Æ Θ(n) nei casi peggiore, migliore e medio
passo 2: rtok=10
– se il numero di chiavi distinte è n la lunghezza della chiave è
almeno log n
array cnt: posizioni degli
indici per array B
Æ in generale: Ω(n log n)
fine passo 2: array A
Politecnico di Milano - Prof. Sara Comai
27
Politecnico di Milano - Prof. Sara Comai
28
7
Radix sort (5)
Informatica 3
• Per migliorare le prestazioni:
– rendere la base r più grande possibile (in base al
numero di record)
Lezione 19 - Modulo 3
– Osservazione: funziona bene per numeri interi
• Non appropriato per numeri reali e stringhe
Confronto tra algoritmi
Politecnico di Milano - Prof. Sara Comai
29
Politecnico di Milano - Prof. Sara Comai
30
Confronto tra algoritmi (2)
Confronto tra algoritmi (1)
valori: interi a 32 bit
input: array random di interi
• Analisi asintotica:
– algoritmi Θ(n2)
– algoritmi Θ(n log n)
– Tra quelli della stessa classe qual è il migliore?
– Per ordinare array di piccole dimensioni qual è il
migliore?
Æ test empirici
/O = versione ottimizzata
/4 e /8 = versione a 4 e 8 bit per passo
Politecnico di Milano - Prof. Sara Comai
31
Politecnico di Milano - Prof. Sara Comai
32
8
Limite inferiore
Albero decisionale
Ordinamento
per inserimento:
• Costo del PROBLEMA di ordinamento
profondità più piccola
del nodo più profondo
dell’albero determina il
limite inferiore:
Ω(n log n)
– Limite superiore: costo asintotico dell’algoritmo più veloce:
O(n log n)
– Limite inferiore: costo migliore di qualsiasi algoritmo che
risolva il problema: Ω(n)
Æ Θ (n log n)
– si dimostra che nessun algoritmo di ordinamento generalpurpose basato sul confronto di chiavi può essere più veloce
di Θ(n log n) nei casi peggiore e medio
– Dimostrazione: le decisioni per i confronti possono essere
rappresentate da un albero decisionale
• albero binario in cui ogni decisione (confronto tra chiavi) è
rappresentata da un ramo dell’albero
Politecnico di Milano - Prof. Sara Comai
33
Politecnico di Milano - Prof. Sara Comai
34
9