Capitolo 4 Ordinamento: lower bound Ω(n log n) e MergeSort ((*) l’intera lezione) Algoritmi e Strutture Dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 2 Stato dell’arte Insertion Sort 2 Insertion Sort 1 Θ(n) Caso migliore T(n) Selection Sort Θ(n 2 ) Caso medio Θ(n 2 ) Caso peggiore Θ(n 2 ) O(n 2 ) S(n) Θ(n) Insertion Sort 3 Θ(n log n)Θ(n 2 ) O(n 2 )Θ(n) Bubble-Sort Θ(n 2 ) Θ(n) Nota: il Bubble-Sort può essere facilmente modificato in modo tale che il caso migliore costi Θ(n). Come?
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 3 Quindi, per il problema dell’ordinamento… Lower bound temporale: (n) –“banale”: dimensione dell’input Upper bound temporale: O(n 2 ) –Insertion Sort 2 e 3 Abbiamo un gap lineare tra upper bound e lower bound! È possibile chiudere tale gap?
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 4 Ordinamento per confronti Dati due elementi a i ed a j, per determinarne l’ordinamento relativo effettuiamo una delle seguenti operazioni di confronto: a i a j ; a i a j ; a i a j ; a i a j ; a i a j 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.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 5 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 a i ed a j (ad esempio effettua il test a i a j ); -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 Lower bound (n log n) per l’ordinamento
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati 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 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 a i e a j ) Nodo foglia: i 1,i 2,…,i n (modella una risposta (output) dell’algoritmo, ovvero una permutazione degli elementi) Albero di decisione
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 7 Esempio Input Riconoscete l’algoritmo associato? È 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.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 8 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) Proprietà
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 9 Lemma: Un albero binario (ovvero, in cui ogni nodo interno ha al più due figli) con k foglie ha altezza h(k) log 2 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 log 2 1=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+log 2 (k/2) =1+log 2 k-log 2 2=log 2 k. QED Altezza in funzione delle foglie
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 10 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à: Il lower bound (n log n) h(n) log 2 (#foglie) log 2 (n!) Formula di Stirling: n! (2 n) 1/2 ·(n/e) n > (n/e) n > log 2 (n/e) n = = n log 2 (n/e) = n log 2 n – n log 2 e = = (n log n) QED =
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 11 Problema dell’ordinamento: –Lower bound - (n log n) albero di decisione –Upper bound – O(n 2 ) 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 Un algoritmo ottimo: il MergeSort (John von Neumann, 1945)
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 12 Esempio di esecuzione Input ed output delle chiamate ricorsive
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 13 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 Fusione di sequenze ordinate 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]
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 14 Merge (A, i 1, f 1, f 2 ) 1. Sia X un array ausiliario di lunghezza f 2 -i i=1 3. i 2 =f while (i 1 f 1 e i 2 f 2 ) do 5. if (A[i 1 ] A[i 2 ]) 6. then X[i]=A[i 1 ] 7. incrementa i e i 1 8. else X[i]=A[i 2 ] 9. incrementa i e i if (i 1 <f 1 ) then copia A[i 1 ;f 1 ] alla fine di X 11. else copia A[i 2 ;f 2 ] alla fine di X 12. copia X in A[i 1 ;f 2 ] fonde A[i 1 ;f 1 ] e A[f 1 +1;f 2 ] output in A[i 1 ;f 2 ] Osservazione: usa l’array ausiliario X Algoritmo di fusione di sequenze ordinate
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 15 Lemma La procedure Merge fonde due sequenze ordinate di lunghezza n 1 e n 2 eseguendo al più n 1 + n 2 -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 è n 1 + n 2. Quindi il numero totale di confronti è n 1 + n QED Numero di confronti: C(n=n 1 + n 2 )=O(n 1 + n 2 )=O(n) (si noti che vale anche C(n)=Ω(min{n 1,n 2 })) Numero di operazioni (confronti + copie)? T(n)= (n 1 + n 2 ) Costo dell’algoritmo di merge
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 16 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) MergeSort
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 17 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{n 1,n 2 })=Ω(min{n/2, n/2})=Ω(n)) Usando il caso 2 del Teorema Master (infatti a=b=2, e quindi f(n) Θ(n)=Θ(n log 2 2 ) Θ(n log b a )), si ottiene C(n) = O(n log 2 2 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 =) Tempo di esecuzione
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati 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) – ·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).
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 19 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))