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