Heap binari e HeapSort.

Slides:



Advertisements
Presentazioni simili
Strutture dati per insiemi disgiunti
Advertisements

Alberi binari Definizione Sottoalberi Padre, figli
Programmazione dinamica: problema della sottosequenza più lunga
Estendere i linguaggi: i tipi di dato astratti
Algoritmi e Strutture Dati
Lez. 91 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Alberi di ricerca.
RB-alberi (Red-Black trees)
Code a priorità (Heap) Definizione
Strutture dati elementari
Alberi binari di ricerca
Code con priorità Ordinamento
Cammini minimi con sorgente singola
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Stesso approccio.
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Ordinamenti ottimi.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Stesso approccio.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Stesso approccio.
Algoritmi Paralleli e Distribuiti a.a. 2008/09 Lezione del 22/05/2009 Prof. ssa ROSSELLA PETRESCHI a cura del Dott. SAVERIO CAMINITI.
U V U V (a) |cfc|=2 prima e dopo (b) |cfc|=2 prima e |cfc|=1 dopo
Algoritmi e strutture Dati - Lezione 7
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl Capitolo 4 Ordinamento:
Il problema del dizionario
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Capitolo 4 Ordinamento: Heapsort Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale.
Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
Capitolo 4 Ordinamento: Selection e Insertion Sort Algoritmi e Strutture Dati.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati Alberi Binari di Ricerca.
Algoritmi e Strutture Dati (Mod. A)
Algoritmi e Strutture Dati
Algoritmi e strutture dati
Algoritmi e Strutture Dati IV. Heap e Code di Priorità
Algoritmi e Strutture Dati 20 aprile 2001
07/04/2003Algoritmi Ricerca in una sequenza di elementi Data una sequenza di elementi, occorre verificare se un elemento fa parte della sequenza oppure.
Algoritmi e Strutture Dati
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Heap binomiali Gli heap binomiali sono strutture dati su cui si possono eseguire efficientemente le operazioni: Make(H) : crea uno heap vuoto Insert(H,
QuickSort Quick-Sort(A,s,d) IF s < d THEN q = Partiziona(A,s,d) Quick-Sort(A,s,q-1) Quick-Sort(A,q + 1,d)
Algoritmo SelectSort Invariante di ciclo: ad ogni passo
Strutture dati per insiemi disgiunti
Vedremo in seguito che (n log n) è un limite stretto per il problema dellordinamento. Per ora ci limitiamo a dimostrare che: La complessità nel caso pessimo.
RB-insert(T, z) // z.left = z.right = T.nil Insert(T, z) z.color = RED // z è rosso. Lunica violazione // possibile delle proprietà degli alberi // rosso-neri.
Heap Ordinamento e code di priorità Ugo de Liguoro.
La complessità media O(n log n) di Quick-Sort vale soltanto se tutte le permutazioni dell’array in ingresso sono ugualmente probabili. In molte applicazioni.
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Cammini minimi da un sorgente
1/32 Algoritmi e Strutture Dati HEAP Anno accademico
alberi completamente sbilanciati
Heap concetti ed applicazioni. maggio 2002ASD - Heap2 heap heap = catasta condizione di heap 1.albero binario perfettamente bilanciato 2.tutte le foglie.
Ordinamento in tempo lineare Il limite inferiore Ω(n log n) vale per tutti gli algoritmi di ordinamento generali, ossia per algoritmi che non fanno alcuna.
Algoritmi e Strutture Dati
Capitolo 8 Code con priorità Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Lo strano mondo degli algoritmi di ordinamento Algoritmi.
1 Ordinamento (Sorting) INPUT: Sequenza di n numeri OUTPUT: Permutazione π = tale che a 1 ’  a 2 ’  … …  a n ’ Continuiamo a discutere il problema dell’ordinamento:
Algoritmi e strutture Dati - Lezione 7 1 Algoritmi di ordinamento ottimali L’algoritmo Merge-Sort ha complessità O(n log(n))  Algoritmo di ordinamento.
1 Ordinamento (Sorting) Input: Sequenza di n numeri Output: Permutazione π = tale che: a i 1  a i 2  ……  a i n Continuiamo a discutere il problema dell’ordinamento:
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Capitolo 4 Ordinamento: Heapsort Algoritmi e Strutture Dati.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Progettare algoritmi.
Algoritmi e Strutture Dati HeapSort. Select Sort: intuizioni L’algoritmo Select-Sort  scandisce tutti gli elementi dell’array a partire dall’ultimo elemento.
Progettare algoritmi veloci usando strutture dati efficienti
Progettare algoritmi veloci usando strutture dati efficienti
Progettare algoritmi veloci usando strutture dati efficienti
Transcript della presentazione:

Heap binari e HeapSort

Algoritmo SelectSort Invariante di ciclo: ad ogni passo gli ultimi i elementi del vettore corrente sono gli i elementi massimi del vettore originale gli ultimi i elementi del vettore corrente sono ordinati Inizializzazione: i = 0 Passo: estrarre l’elemento massimo dal vettore [1..n-i] e scambiarlo con quello in posizione n-i Condizione di arresto: i = n

Pseudocodice di SelectSort SelectSort(n,A) For j = n downto 2 do {estrai il massimo e mettilo in coda} j_ max = FindMax(A,j) “scambia A[j_max] e A[j]” FindMax(A,j) i_max = 1 For i = 2 to j do If A[i_max] < A[i] then i_max = i return i_max

SelectSort Scandisce la sequenza dall’ultimo elemento al primo Ad ogni iterazione (FindMax) cerca l’elemento massimo A[j_max] nella sottosequenza corrente A[1,…,j] scambia l’ultimo elemento con quello massimo (facendo uscire l’elemento massimo dalla sequenza e ricompattandola) j_max j 1 n disordinati ordinati Algoritmo di ordinamento stabile (perché?) Complessità O(n2) in ogni caso (anche in quello migliore)

L’algoritmo di ordinamento HeapSort E’ una variante di SelectSort in cui si estrae l’elemento massimo in tempo costante grazie a uno heap Lo heap è un albero binario quasi completo (struttura), in cui le etichette dei nodi rispettano certe condizioni Albero binario: insieme vuoto (albero vuoto o nullo) unione di tre sottoinsiemi disgiunti un nodo detto radice un albero binario detto sottoalbero sinistro un albero binario detto sottoalbero destro

Alberi binari nodo radice sottoalbero sinistro sottoalbero destro

Qualche definizione sugli alberi Nodo foglia (o foglia) di un albero è un nodo i cui sottoalberi sono vuoti (non ha figli) Nodo interno di un albero è un nodo che ha figli Percorso dal nodo i al nodo j è la sequenza di archi da attraversare per raggiungere il nodo j dal nodo i Grado di un nodo è il numero dei suoi figli Profondità di un nodo è il numero di archi del percorso da esso alla radice Altezza di un albero è la profondità massima dei suoi nodi

Alberi percorso dalla radice al nodo k nodi interni nodi foglia Radice Profondità 3 Profondità 2 Profondità 1 Profondità 0 Altezza 3 Radice Grado 1 Grado 2 Grado 0 nodi interni nodi foglia

Alberi binari completi (e quasi) Albero binario: tutti i nodi hanno grado  2 Albero binario completo: tutti i nodi interni hanno grado 2 tutte le foglie hanno la stessa profondità Albero binario quasi completo tutte le foglie hanno profondità h o h-1 tutti i nodi interni hanno grado 2, eccetto al più uno se esiste un nodo di grado 1 è a profondità h-1 ha solo il figlio sinistro i nodi alla sua destra (se esistono) sono foglie

Alberi binari quasi completi profondità 0 nodo di grado 1 profondità h-1 profondità h nodi foglia

Proprietà di uno heap Un albero heap è un albero binario quasi completo con etichette sui nodi, tali che per ogni nodo l’etichetta di entrambi i nodi figli non supera quella del padre. Condizione sulla struttura dell’albero Condizione sull’etichettatura dell’albero

Un esempio di heap La relazione d’ordine è fra padre e figli, 45 34 28 30 25 22 12 14 21 15 16 20 La relazione d’ordine è fra padre e figli, non fra i due figli!

Heap e ordinamenti parziali Uno heap rappresenta un ordinamento parziale, cioè una relazione tra elementi di un insieme riflessiva: x è in relazione con se stesso x R x antisimmetrica: se x è in relazione con y e y è in relazione con x, allora x = y x R y  y R x  x = y transitiva: se x è in relazione con y e y è in relazione con z, allora x è in relazione con z x R y  y R z  x R z Esempi: le relazioni  e  (NON le relazioni > e < !)

Heap e ordinamenti parziali Un albero binario di ricerca rappresenta un ordinamento totale: in un ordinamento totale per ogni coppia di elementi x e y vale o x R y o y R x Un ordinamento parziale è più debole di uno totale: possono esservi coppie di elementi privi di relazione Gli ordinamenti parziali modellano gerarchie con informazione incompleta o elementi con uguali valori Uno heap può essere implementato in vari modi; ad es., come un albero a puntatori, oppure come un array

Rappresentazione di uno heap come array 45 1 2 3 4 5 6 7 8 9 10 11 12 34 28 30 25 22 12 14 21 15 16 20 1 2 3 4 5 6 7 8 9 10 11 12 45 34 28 30 25 22 12 14 21 15 16 20

Rappresentazione di uno heap come array la radice dello heap sta nella prima posizione dell’array se un nodo dello heap sta nella posizione i dell’array il figlio sinistro sta nella posizione 2i il figlio destro sta nella posizione 2i +1 viceversa, un array A rappresenta uno heap quando A[i ]  A[2i ] e A[i]  A[2i+1]

Rappresentazione di uno heap come array 45 1 34 28 2 3 30 25 22 12 4 5 6 7 14 21 15 16 20 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 45 34 28 30 25 22 12 14 21 15 16 20

Operazioni elementari su uno heap LeftSubtree(i) {restituisce la radice del sottoalbero sinistro} return 2i RightSubtree(i) {restituisce la radice del sottoalbero destro} return 2i + 1 Father (i) {restituisce il nodo padre di i} return i/2 Indichiamo con heapsize(A)  n la dimensione dello heap Heapify(A,i): ripristina la proprietà di heap nel sottoalbero radicato in i, assumendo che valga già per i sottoalberi destro e sinistro di i BuildHeap(A): trasforma il generico array A in uno heap

Heapify Dati due heap H1 e H2 con radici k >1 e k+1 Si possono fondere i due heap in un albero H con radice in posizione i = k/2 Se l’ elemento v in posizione A[i] non è v  A[k] e v  A[k+1], allora H non è uno heap. Per renderlo tale: si scambia A[i] con la maggiore fra le radici di H1 e H2 si applica Heapify ricorsivamente al sottoalbero selezionato (con la nuova radice v in posizione A[2i] o A[2i+1])

Algoritmo Heapify Heapify(A,i) l = LeftRoot(i) r = RightRoot(i) i_max = i If l  heapsize(A) and A[l] > A[i_max] then i_max = l If r  heapsize(A) and A[r] > A[i_max] then i_max = r If i_max  i then “scambia A[i] e A[i_max]” Heapify(A,i_max)

Un esempio di applicazione di Heapify i_max = i If l  heapsize(A) and A[l] > A[i_max] then i_max = l If r  heapsize(A) and A[r] > A[i_max] then i_max = r 45 1 A i 14 28 2 3 34 i_max 34 l 25 r 22 12 4 5 6 7 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di Heapify If i_max  i then “scambia A[i] e A[i_max]” ... 45 1 A 34 14 i 14 28 2 3 i_max 34 l 25 r 22 12 4 5 6 7 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di Heapify If i_max  i then “scambia A[i] e A[i_max]” Heapify(A,i_max) 45 1 34 28 2 3 A i 14 25 22 12 4 5 6 7 l 30 r 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di Heapify i_max = i If l  heapsize(A) and A[l] > A[i_max] then i_max = l If r  heapsize(A) and A[r] > A[i_max] then i_max = r 45 1 34 28 2 3 A i 14 25 22 12 4 5 6 7 i_max 30 l 30 r 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di Heapify If i_max  i then “scambia A[i] e A[i_max]” ... 45 1 34 28 2 3 A 30 14 i 14 25 22 12 4 5 6 7 i_max l 30 30 r 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di Heapify If i_max  i then “scambia A[i] e A[i_max]” Heapify(A,i_max) 45 1 34 28 2 3 30 25 22 12 4 5 6 7 A i 14 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di Heapify i_max = i If l  heapsize(A) and A[l] > A[i_max] then i_max = l If r  heapsize(A) and A[r] > A[i_max] then i_max = r 45 I test sono falsi l > heapsize(A) r > heapsize(A) per cui i_max = i (caso base) 1 34 28 2 3 30 25 22 12 4 5 6 7 A i 14 21 15 16 Heapify termina! Ora vale la proprietà heap 20 8 9 10 11 12

Complessità di Heapify T(n) = max[O(1),O(1)+T(n’)] Heapify(A,i) l = LeftRoot(i) r = RightRoot(i) i_max = i If l  heapsize(A) and A[l] > A[i_max] then i_max = l If r  heapsize(A) and A[r] > A[i_max] then i_max = r If i_max  i then “scambia A[i] e A[i_max]” Heapify(A,i_max) O(1) O(1) f(n) = T(n’)

Complessità di Heapify Ad ogni chiamata ricorsiva, Heapify viene eseguito su un sottoalbero di n’ nodi dell’albero di n nodi n’  2/3 n Sottoalbero completo di altezza h-1 Sottoalbero completo di altezza h-2 45 1 n’’ n’ 34 28 2 3 30 25 22 12 4 5 6 7 n’/n è massimo 14 21 15 16 8 9 10 11

Complessità di Heapify 45 1 n’’ n’ 34 28 2 3 30 25 22 12 4 5 6 7 14 21 15 n’/n non è massimo (n’ è più piccolo!) 8 9 10

Complessità di Heapify 45 1 n’ n’’ 34 28 2 3 30 25 22 12 4 5 6 7 14 21 15 16 20 n’/n non è massimo (n è più grande!) 8 9 10 11 12

Complessità di Heapify Sottoalbero completo di altezza h-1 Sottoalbero completo di altezza h-2 45 1 n’’ n’ 34 28 2 3 30 25 22 12 4 5 6 7 n’ = 2h - 1 n’’ = 2h-1 - 1 n = 1 + n’ + n’’ = 32h-1 - 1 14 21 15 16 8 9 10 11 n’/n = 2h-1/(3 2h-1 -1)  2/3

Complessità di Heapify T(n) = max[O(1),max(O(1),O(1) + T(n’))]  max[O(1),max(O(1),O(1) + T(2n/ 3))]  T(2n/3) + (1) T(n) = O (log n) Sempre nel caso peggiore, T(n)  T(n/3) + (1) T(n) =  (log n) Heapify impiega tempo proporzionale all’altezza dell’albero T(n) = (log n)

BuildHeap Trasforma l’array A in uno heap riordinando i suoi elementi attraverso l’algoritmo Heapify Heapify richiede che i due sottoalberi di ogni elemento siano già heap, ma gli ultimi n/2 elementi dell’array lo sono già, perché sono foglie, cioè radici di sottoalberi vuoti Quindi, basta inserire nello heap i primi n/2 elementi, usando Heapify per ripristinare la proprietà heap sui sottoalberi radicati in essi BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i)

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 20 12 30 21 25 16 22 14 1 45 28 2 3 34 15 20 20 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 25 16 22 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 22 12 30 21 25 16 20 14 1 45 28 22 20 heap 2 3 34 15 20 20 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 25 16 22 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 20 12 30 21 25 16 22 14 1 45 28 2 3 34 15 15 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 25 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 25 20 12 30 21 15 16 22 14 i = 5 25 15 heap 1 45 28 2 3 34 15 15 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 25 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 20 12 30 21 25 16 22 14 1 45 heap 28 2 3 34 34 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 20 12 30 21 25 16 22 14 1 45 heap 28 28 2 3 34 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 20 12 30 21 25 16 22 14 1 45 45 heap 28 2 3 34 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 14 45 28 34 15 20 12 30 21 25 16 22 14 14 1 45 28 2 3 34 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 45 14 28 34 15 20 12 30 21 25 16 22 14 45 14 1 14 45 28 2 3 34 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 45 34 28 14 15 20 12 30 21 25 16 22 14 45 14 1 34 28 2 3 14 34 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 45 34 28 30 15 20 12 14 21 25 16 22 45 14 14 1 34 28 2 3 30 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 30 14 21 15 16 20 8 9 10 11 12

Un esempio di applicazione di BuildHeap 1 2 3 4 5 6 7 8 9 10 11 12 45 34 28 30 15 20 12 14 21 25 16 22 45 14 14 1 heap 34 28 2 3 30 25 22 12 4 5 6 7 BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 14 21 15 16 20 8 9 10 11 12

Complessità di BuildHeap BuildHeap chiama n/2 volte Heapify E’ allora TBH(n) = n/2 TH(n) = O(n log n)? Sì, ma si può stringere la stima sino a TBH(n) = O(n) Costruire uno heap di n elementi costa solo O(n)!

Complessità di BuildHeap BuildHeap chiama Heapify (n/2 volte su heap di altezza 0) (inutile eseguire) n/4 volte su heap di altezza 1 n/8 volte su heap di altezza 2 … n/2h+1 volte su heap di altezza h 14 1 45 28 2 3 34 15 20 12 4 5 6 7 30 21 25 16 22 8 9 10 11 12

Complessità di BuildHeap Poiché TH = O(log n) e Poiché ,

HeapSort HeapSort è una variante di SelectSort che mantiene la sequenza in uno heap, facilitando così cui la ricerca dell’elemento massimo si costruisce uno heap a partire dall’array non ordinato A si scandisce l’array a partire dall’ultimo elemento e ad ogni passo la radice A[1] (che è l’elemento massimo) viene scambiata con l’ultimo elemento dello heap corrente si riduce di uno la dimensione corrente dello heap si ripristina la proprietà heap con Heapify

HeapSort e SelectSort SelectSort(n,A) For j = n downto 2 do j_ max = FindMax(A,j) “scambia A[j_max] e A[j]” HeapSort(A) BuildHeap(A) For j = n downto 2 do { heapsize(A) = j } “scambia A[1] e A[j]” { j_ max = 1 } Heapify(A[1,…,j-1],1) { ripristina lo heap, ridotto}

Intuizioni su HeapSort 1 disordinati costruisci heap max n 1 parzialmente ordinati heap max ordinati parzialmente ordinati heap i scambio + Heapify n 1

Un esempio di esecuzione di HeapSort HeapSort(A) BuildHeap(A) … 45 14 1 45 34 28 2 3 30 34 25 15 22 20 12 4 5 6 7 14 30 21 15 25 16 20 22 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 12 45 20 45 14 1 34 45 28 28 2 3 30 34 25 15 22 20 12 12 4 5 6 7 14 30 21 21 15 25 16 16 20 22 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 12 20 45 14 1 34 45 28 28 2 3 30 34 25 15 22 20 12 12 4 5 6 7 14 30 21 21 15 25 16 16 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 12 30 21 20 34 20 45 14 1 34 45 28 28 2 3 30 34 25 15 22 20 12 12 4 5 6 7 14 30 21 21 15 25 16 16 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 11 34 16 20 34 45 14 1 30 28 28 2 3 21 25 15 22 20 12 12 4 5 6 7 14 30 20 15 25 16 16 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 11 16 20 34 45 14 1 30 28 28 2 3 21 25 15 22 20 12 12 4 5 6 7 14 30 20 15 25 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 11 25 16 30 20 16 34 45 14 1 30 28 28 2 3 21 25 15 22 20 12 12 4 5 6 7 14 30 20 15 25 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 10 30 15 30 1 25 28 28 2 3 21 16 22 20 12 12 4 6 7 5 14 30 20 15 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 10 30 15 1 25 28 28 2 3 21 16 22 20 12 12 4 6 7 5 14 30 20 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 10 30 15 22 15 28 1 25 28 28 2 3 21 16 22 20 12 12 4 6 7 5 14 30 20 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 9 20 28 28 30 1 25 22 28 2 3 21 16 15 20 12 12 4 6 7 5 14 30 20 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 9 20 1 25 22 28 2 3 21 16 15 20 12 12 4 6 7 5 14 30 28 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 9 20 21 25 20 1 25 22 28 2 3 21 16 15 20 12 12 4 6 7 5 14 30 28 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 8 25 14 25 1 21 22 28 2 3 20 16 15 20 12 12 4 6 7 5 14 30 28 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 8 25 14 1 21 22 28 2 3 20 16 15 20 12 12 4 6 7 5 25 28 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 8 25 14 15 14 22 1 21 22 28 2 3 20 16 15 20 12 12 4 6 7 5 25 28 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 7 22 12 22 1 21 15 2 3 20 16 14 12 12 4 6 7 5 25 28 30 34 45 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 7 12 1 21 15 2 3 20 16 14 4 6 5 22 25 28 30 34 45 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 7 12 20 21 12 1 21 15 2 3 20 16 14 4 6 5 22 25 28 30 34 45 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 6 21 21 14 1 20 15 2 3 12 20 16 14 4 6 5 22 25 28 30 34 45 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 6 14 21 1 20 15 2 3 12 16 4 5 21 22 25 28 30 34 45 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 6 14 16 20 14 21 1 20 15 2 3 12 16 4 5 21 22 25 28 30 34 45 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 5 20 14 20 1 16 15 2 3 12 14 4 5 21 22 25 28 30 34 45 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 5 20 14 1 16 15 2 3 12 4 20 21 22 25 28 30 34 45 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 5 14 16 20 14 1 16 15 2 3 12 4 20 21 22 25 28 30 34 45 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 4 16 12 16 1 14 15 2 3 12 4 20 21 22 25 28 30 34 45 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 4 12 16 1 14 15 2 3 16 20 21 22 25 28 30 34 45 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 4 12 16 12 15 1 14 15 2 3 16 20 21 22 25 28 30 34 45 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 3 15 12 15 1 14 12 2 3 16 20 21 22 25 28 30 34 45 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 3 12 15 1 14 2 15 16 20 21 22 25 28 30 34 45 3 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 3 12 14 12 15 1 14 2 15 16 20 21 22 25 28 30 34 45 3 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 2 14 12 14 1 12 2 15 16 20 21 22 25 28 30 34 45 3 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 2 12 12 1 14 15 16 20 21 22 25 28 30 34 45 2 3 4 5 6 7 8 9 10 11 12

Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) j = 2 L’array A ora è ordinato! 12 14 15 16 20 21 22 25 28 30 34 45 1 2 3 4 5 6 7 8 9 10 11 12

Invariante di ciclo per HeapSort Invariante di ciclo: ad ogni passo gli ultimi i elementi del vettore corrente sono gli i elementi massimi del vettore originale gli ultimi i elementi del vettore corrente sono ordinati i primi n-i elementi del vettore corrente formano uno heap Inizializzazione: i = 0 e BuildHeap() Passo: estrarre l’elemento massimo dal vettore [1..n-i] e scambiarlo con quello in posizione n-i e recuperare la proprietà heap nel vettore [1..n-i-1] Condizione di arresto: i = n

Complessità di HeapSort HeapSort(A) BuildHeap(A) For j = n downto 2 do “scambia A[1] e A[j]” Heapify(A[1,…,j-1],1) Nel caso peggiore HeapSort chiama 1 volta BuildHeap n-1 volte Heapify sullo heap corrente THS(n) = max[O(n), (n-1) max(O(1), TH(n))] = max[O(n), max(O(n), O(n log n))] = O(n log n)

Conclusioni su HeapSort E’ un algoritmo di ordinamento sul posto per confronto e impiega tempo O(n log n) Non è un algoritmo elementare Sfrutta le proprietà della struttura dati astratta heap. Dimostra che una buona rappresentazione dei dati spesso facilita il progetto di buoni algoritmi