La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Heap binari e HeapSort. Algoritmo SelectSort Invariante di ciclo : ad ogni passo gli ultimi i elementi del vettore corrente sono gli i elementi massimi.

Presentazioni simili


Presentazione sul tema: "Heap binari e HeapSort. Algoritmo SelectSort Invariante di ciclo : ad ogni passo gli ultimi i elementi del vettore corrente sono gli i elementi massimi."— Transcript della presentazione:

1 Heap binari e HeapSort

2 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 lelemento massimo dal vettore [1..n-i] e scambiarlo con quello in posizione n-i Condizione di arresto: i = n

3 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 Pseudocodice di SelectSort

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

5 Lalgoritmo di ordinamento HeapSort E una variante di SelectSort in cui si estrae lelemento 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

6 Alberi binari sottoalbero sinistro sottoalbero destro nodo radice

7 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

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

9 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

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

11 Condizione sulla struttura dellalbero Proprietà di uno heap Un albero heap è un albero binario quasi completo con etichette sui nodi, tali che per ogni nodo letichetta di entrambi i nodi figli non supera quella del padre. Condizione sulletichettatura dellalbero

12 Un esempio di heap La relazione dordine è fra padre e figli, non fra i due figli!

13 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 < !)

14 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

15 20 Rappresentazione di uno heap come array

16 Rappresentazione di uno heap come array la radice dello heap sta nella prima posizione dellarray se un nodo dello heap sta nella posizione i dellarray – 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]

17 Rappresentazione di uno heap come array

18 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

19 Heapify Dati due heap H 1 e H 2 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 H 1 e H 2 si applica Heapify ricorsivamente al sottoalbero selezionato (con la nuova radice v in posizione A[2i] o A[2i+1])

20 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)

21 Un esempio di applicazione di Heapify 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 lr A 34 i_max

22 Un esempio di applicazione di Heapify i If i_max i then scambia A[i] e A[i_max]... i_max lr A 34 14

23 Un esempio di applicazione di Heapify i If i_max i then scambia A[i] e A[i_max] Heapify(A,i_max) lr A

24 Un esempio di applicazione di Heapify i lr A 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 i_max 30

25 Un esempio di applicazione di Heapify i lr A i_max 30 If i_max i then scambia A[i] e A[i_max]

26 Un esempio di applicazione di Heapify i If i_max i then scambia A[i] e A[i_max] Heapify(A,i_max) A

27 Un esempio di applicazione di Heapify i A I test sono falsi l > heapsize(A) r > heapsize(A) per cui i_max = i (caso base) 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 Heapify termina! Ora vale la proprietà heap

28 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) Complessità di Heapify T(n) = max[O(1),O(1)+ T(n) ] O(1)O(1) O(1)O(1) f(n) = T(n)

29 Complessità di Heapify Ad ogni chiamata ricorsiva, Heapify viene eseguito su un sottoalbero di n nodi dellalbero di n nodi n 2/3 n n/n è massimo n n Sottoalbero completo di altezza h-1 Sottoalbero completo di altezza h-2

30 Complessità di Heapify n n n/n non è massimo (n è più piccolo!)

31 Complessità di Heapify n n n/n non è massimo (n è più grande!)

32 Complessità di Heapify n = 2 h - 1 n = 2 h n = 1 + n + n = 3 2 h n n Sottoalbero completo di altezza h-1 Sottoalbero completo di altezza h-2 n/n = 2 h -1/(3 2 h-1 -1) 2/3

33 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 allaltezza dellalbero T(n) = (log n) Complessità di Heapify

34 BuildHeap Trasforma larray A in uno heap riordinando i suoi elementi attraverso lalgoritmo Heapify Heapify richiede che i due sottoalberi di ogni elemento siano già heap, ma gli ultimi n/2 elementi dellarray 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)

35 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) i = 6i = 6 20

36 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) heap i = 6i = 6

37 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 15 i = 5i = 5

38 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 15 i = 5i = heap i = 5i = 5

39 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 34 heap i = 4i = 4

40 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) heap 28 i = 3i = 3

41 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 45 heap i = 2i = 2

42 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) 14 i = 1i = 1

43 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) i = 1i = 1

44 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) i = 1i = 1

45 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) i = 1i = 1

46 Un esempio di applicazione di BuildHeap BuildHeap(A) For i = length(A)/2 downto 1 do Heapify(A,i) heap i = 1i = 1

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

48 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/2 h+1 volte su heap di altezza h

49 Complessità di BuildHeap Poiché Poiché T H = O(log n) e,

50 HeapSort HeapSort è una variante di SelectSort che mantiene la sequenza in uno heap, facilitando così cui la ricerca dellelemento massimo si costruisce uno heap a partire dallarray non ordinato A si scandisce larray a partire dallultimo elemento e ad ogni passo la radice A[1] (che è lelemento massimo) viene scambiata con lultimo elemento dello heap corrente si riduce di uno la dimensione corrente dello heap si ripristina la proprietà heap con Heapify

51 HeapSort e SelectSort 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} SelectSort(n,A) For j = n downto 2 do j_ max = FindMax(A,j) scambia A[j_max] e A[j]

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

53 Un esempio di esecuzione di HeapSort HeapSort(A) BuildHeap(A) …

54 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

55 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j = 12

56 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 =

57 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

58 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

59 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 =

60 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

61 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

62 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 =

63 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

64 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

65 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 =

66 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

67 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

68 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 =

69 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 =

70 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 =

71 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 =

72 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

73 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

74 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 =

75 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

76 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

77 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 =

78 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

79 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

80 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 =

81 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

82 Un esempio di esecuzione di HeapSort HeapSort(A) … For j = n downto 2 doscambia A[1] e A[j] Heapify(A[1,…,j-1],1) j =

83 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 =

84 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 =

85 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 =

86 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 = Larray A ora è ordinato!

87 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 lelemento 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

88 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 T HS (n) = max[O(n), (n-1) max(O(1), T H (n))] = max[O(n), max(O(n), O(n log n))] = O(n log n)

89 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


Scaricare ppt "Heap binari e HeapSort. Algoritmo SelectSort Invariante di ciclo : ad ogni passo gli ultimi i elementi del vettore corrente sono gli i elementi massimi."

Presentazioni simili


Annunci Google