Algoritmi e Strutture Dati HeapSort. Select Sort: intuizioni L’algoritmo Select-Sort  scandisce tutti gli elementi dell’array a partire dall’ultimo elemento.

Slides:



Advertisements
Presentazioni simili
Strutture dati per insiemi disgiunti
Advertisements

Alberi binari Definizione Sottoalberi Padre, figli
Algoritmi e Strutture Dati
Programmazione dinamica: problema della sottosequenza più lunga
RB-alberi (Red-Black trees)
Code a priorità (Heap) Definizione
Strutture dati elementari
Alberi binari di ricerca
Code con priorità Ordinamento
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.
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.
Esercizi su alberi binari
Algoritmi e strutture Dati - Lezione 7
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.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl Alberi AVL (Adelson-Velskii.
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)
Alberi di Ricorrenza Gli alberi di ricorrenza rappresentano un modo conveniente per visualizzare i passi di sostitu- zione necessari per risolvere una.
Algoritmi e Strutture Dati
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.
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.
Esercizi su alberi binari
Heap binari e HeapSort.
Algoritmo SelectSort Invariante di ciclo: ad ogni passo
Strutture dati per insiemi disgiunti
Didattica dei Fondamenti dell’Informatica 2 Seconda giornata: progettare un algoritmo corretto, efficiente, e possibilmente ottimo! Guido Proietti
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.
1/32 Algoritmi e Strutture Dati HEAP Anno accademico
Heap concetti ed applicazioni. maggio 2002ASD - Heap2 heap heap = catasta condizione di heap 1.albero binario perfettamente bilanciato 2.tutte le foglie.
Alberi Alberi radicati : alberi liberi in cui un vertice è stato scelto come radice. Alberi liberi : grafi non orientati connessi e senza cicli. Alberi.
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
MODULO STRUTTURE DATI FONDAMENTALI: Strutture dinamiche
Capitolo 8 Code con priorità Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
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.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Soluzione esercizio.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Soluzione esercizio.
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.
Capitolo 6 Il problema del dizionario Algoritmi e Strutture Dati.
Didattica e Fondamenti degli Algoritmi e della Calcolabilità Quinta giornata Risolvere efficientemente un problema in P: ancora sulla sequenza di Fibonacci.
Didattica e Fondamenti degli Algoritmi e della Calcolabilità Sesta giornata Risolvere efficientemente un problema in P: Il problema dell’ordinamento: Insertion.
GLI ALGORITMI DI ORDINAMENTO
Capitolo 4 Ordinamento: lower bound Ω(n log n) e MergeSort ((*) l’intera lezione) Algoritmi e Strutture Dati.
Progettare algoritmi veloci usando strutture dati efficienti
Progettare algoritmi veloci usando strutture dati efficienti
Alberi binari Definizione Sottoalberi Padre, figli
Progettare algoritmi veloci usando strutture dati efficienti
HeapSort Stesso approccio incrementale del selectionSort Tipo di dato
Transcript della presentazione:

Algoritmi e Strutture Dati HeapSort

Select Sort: intuizioni L’algoritmo Select-Sort  scandisce tutti gli elementi dell’array a partire dall’ultimo elemento fino all’inizio e ad ogni iterazione:  Viene cercato l’elemento massimo nella parte di array precedente l’elemento corrente  l’elemento massimo viene scambiato con l’elemento corrente n 1 max ordinati disordinati i

Select Sort Select-Sort(A) FOR i = length[A] DOWNTO 2 DO max = Findmax(A,i) “scambia A[max] e A[i]” Findmax(A,x) max = 1 FOR i = 2 to x DO IF A[max] < A[i] THEN max = i return max

Heap Sort L’algoritmo Heap-Sort :  è una variazione di Select-sort in cui la ricerca dell’elemento massimo è facilitata dall’utilizzo di una opportuna struttura dati  la struttura dati è chiamata heap  lo heap è una variante della struttura dati albero binario  in uno heap l’elemento massimo può essere acceduto in tempo costante.

Alberi binari Un albero binario è una struttura dati astratta definita come un insieme finito di nodi che  è vuoto oppure  è composto da tre insiemi disgiunti di nodi:  un nodo radice  un albero binario detto sottoalbero sinistro  un albero binario detto sottoalbero destro

Alberi binari sottoalbero sinistro sottoalbero destro nodo radice

Alberi binari sottoalbero destro nodo radice sottoalbero destro Radice del sotto- albero sinistro sottoalbero sinistro

Alberi binari nodo radice sottoalbero destro sottoalbero sinistro sottoalbero destro Radice del sotto- albero sinistro Radice del sotto- albero destro sottoalbero sinistro

Alberi binari nodo radice sottoalbero sinistro sottoalbero destro

Alberi binari nodo radice nodo i nodo j nodo k figli del nodo i padre dei nodi j e k arco dal nodo i al nodo k

Alberi binari  In nodo di un albero binario si dice nodo foglia (o solo foglia) se non ha figli (cioè se entrambi i sottoalberi di cui è radice sono vuoti)  Un nodo si dice nodo interno se ha almeno un figlio  Un percorso dal nodo i al nodo j è la sequenza di archi che devono essere attraversati per raggiungere il nodo j dal nodo i

Alberi binari nodo radice nodi interni nodi foglia percorso dalla radice al nodo k nodo k

Alberi binari  In un albero binario la profondità di un nodo è la lunghezza del percorso dalla radice al nodo (cioè il numero di archi tra la radice e il nodo)  La profondità maggiore di un nodo all’interno di un albero è l’altezza dell’albero.  Il grado di un nodo è il numero di figli di quel nodo.

Alberi binari nodo radice Profondità 3 Profondità 2 Profondità 1 Profondità 0

Alberi binari nodo radice Profondità 3 Profondità 2 Profondità 1 Profondità 0 Altezza 3

Alberi binari nodo radice Profondità 2 Profondità 1 Profondità 0 Altezza 3 Grado 1 Grado 2 Profondità 3

Alberi binari completo Un albero binario si dice completo se  tutte le foglie hanno la stessa profondità h  tutti i nodi interni hanno grado 2  Un albero completo di n nodi ha altezza esattamente  log 2 n .  Un albero completo di altezza h ha esattamente 2 h+1 -1 nodi.

Alberi binari completo n = 15 e altezza h =  log 2 n  = n = 2 h = = 15

Alberi binari quasi completo Un albero binario si dice quasi completo se ¶ tutte le foglie hanno profondità h o h-1, dove h è l’altezza dell’albero · tutti i nodi interni hanno grado 2, eccetto al più uno.

Alberi binari quasi completo nodi foglia profondità h profondità h-1 profondità 0 nodo con un solo figlio

Condizioni 1 e 2 definiscono la forma dell’albero Proprietà di uno Heap Un Albero Heap è un albero binario tale che per ogni nodo i: ¶ tutte le foglie hanno profondità h o h-1, dove h è l’altezza dell’albero; · tutti i nodi interni hanno grado 2, eccetto al più uno; ¸ entrambi i nodi j e k figli di i sono NON maggiori di i.

Proprietà di uno Heap Un Albero Heap è un albero binario tale che per ogni nodo i: ¶ tutte le foglie hanno profondità h o h-1, dove h è l’altezza dell’albero; · tutti i nodi interni hanno grado 2, eccetto al più uno; ¸ entrambi i nodi j e k figli di i sono NON maggiori di i. Condizione 3 definisce l’etichettatura dell’albero

Proprietà di uno Heap Un Albero Heap è un albero binario quasi completo tale che per ogni nodo i: l entrambi i nodi j e k figli di i sono NON maggiori di i.

Heap Heap NON impone alcuna relazione di ordinamento tra I figli di un nodo

Heap e Ordinamenti Parziali Un Albero Heap è un albero binario quasi completo tale che per ogni nodo i:  entrambi i nodi j e k figli di i sono NON maggiori di i. Uno Heap rappresenta un Ordiamento Parziale

Heap e Ordinamenti Parziali Un Ordinamento Parziale è una relazione tra elementi di un insieme che è:  Riflessiva: x è in relazione con se stesso  Anti-simmetrica: se x è in relazione con y e y è in relazione con x allora x = y  Transitiva: se x è in relazione con y e y è in relazione con z allora x è in relazione con z Esempi: le relazioni  e  le relazioni >, < NON sono ordinamenti parziali

Heap e Ordinamenti Parziali Gli Ordinamenti Parziali possono essere usati per modellare gerarchie con informazione incompleta o elementi con uguali valori L’ordinamento parziale definito da uno Heap è una nozione più debole di un ordinamento totale, infatti uno Heap  è più semplice da costruire  è molto utile ma meno dell’ordinamento totale

Implementazione di uno Heap Uno Heap può essere implementato in vari modi:  come un albero a puntatori  come un array  ….

Heap: da albero ad array

Heap: da albero ad array Uno Heap può essere implementato come un array A in cui:  la radice dello Heap sta nella posizione A[0] dell’array  se il nodo i dello Heap sta nella posizione A[i ] dell’array,  il figlio sinistro di i sta nella posizione A[2i ]  il figlio destro di i sta nella posizione A[2i +1]

Heap: da albero ad array

Heap: da albero ad array

Heap: da albero ad array

Heap: da albero ad array

Heap: da albero ad array

Heap: da albero ad array

Proprietà di uno Heap Un Albero Heap è un albero binario quasi completo tale che per ogni nodo i:  entrambi i nodi j e k figli di i sono NON maggiori di i. Un array A è uno Heap se A[i ]  A[2i ] e A[i]  A[2i+1]

Operazioni elementari su uno Heap SINISTRO(i) return 2i DESTRO(i) return 2i + 1 PADRE(i) return  i/2  heapsize[A]  n è la lunghezza dello Heap

Operazioni su uno Heap  Heapify(A,i) : ripristina la proprietà di Heap al sottoalbero radicato in i assumendo che i suoi sottoalberi destro e sinistro siano già degli Heap  Costruisci-Heap(A) : produce uno Heap a partire dall’array A non ordinato  HeapSort(A) : ordina l’array A sul posto.

Heapify: Intuizioni Heapify(A,i) : dati due Heap H 1 e H 2 con radici SINISTRO(i) e DESTRO(i) e un nuovo elemento v in posizione A[i]  se lo Heap H con radice A[i]= v viola la proprietà di Heap allora:  metti in A[i] la più grande tra le radici degli Heap H1 e H2  applica Heapify ricorsivamente al sottoalbero selezionato (con radice A[2i] o A[2i+1] ) e all’elemento v (ora in posizione A[2i] o A[2i+1] ).

Algoritmo Heapify Heapify(A,i) l = SINISTRO (i) r = DESTRO(i) IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i IF r  heapsize[A] AND A[r] > A[maggiore] THEN maggiore = r IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore)

Heapify i … IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i … lr

Heapify i … IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i … maggiore lr

Heapify i … IF r  heapsize[A] AND A[r] > A[maggiore] THEN maggiore = r … maggiore lr

Heapify i … IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) … maggiore lr

Heapify i … IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) … maggiore lr

Heapify i … IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) … maggiore lr

Heapify i … IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) … lr

Heapify i lr … IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i …

Heapify i lr … IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i … maggiore

Heapify i lr maggiore … IF r  heapsize[A] AND A[r] > A[maggiore] THEN maggiore = r …

Heapify i lr maggiore … IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) …

Heapify i … IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) …

Heapify i … IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i IF r  heapsize[A] AND A[r] > A[maggiore] THEN maggiore = r … Entrambi i test sono falsi perché l e r sono maggiori di heapsize[A]

Heapify i Heapify termina! È stata ripristi- nata la proprietà Heap

Heapify(A,i) l = SINISTRO(i) r = DESTRO(i) IF l  heapsize[A] AND A[l] > A[i] THEN maggiore = l ELSE maggiore = i IF r  heapsize[A] AND A[r] > A[maggiore] THEN maggiore = r IF maggiore  i THEN “scambia A[i] e A[maggiore]” Heapify(A,maggiore) Complessità di Heapify T(n) = max(O(1),max(O(1),T(?) + O(1))

Complessità di Heapify:caso peggiore T(n) = max(O(1),max(O(1),T(?) + O(1)) Nel caso peggiore Heapify ad ogni chiamata ricorsiva, viene eseguito su un numero di nodi che è minore dei 2/3 del numero di nodi correnti n. Cioè il numero di nodi n s del sottoalbero su cui Heapify è chiamato ricorsivamente è al più 2/3 n (o n s  2/3 n )

Complessità di Heapify:caso peggiore nsns nrnr n s /n ha valore massimo

Complessità di Heapify:caso peggiore nsns nrnr n s /n è minore del massimo (n s è più piccolo)

Complessità di Heapify:caso peggiore nsns nrnr n s /n è minore del massimo (n è più grande)

Complessità di Heapify:caso peggiore Albero completo di altezza h-1 Albero completo di altezza h-2 n = h h-1 -1 = 3 2 h Numero di nodi n r =2 h-1 -1 Numero di nodi n s =2 h -1 nsns nrnr

Complessità di Heapify:caso peggiore Albero completo di altezza h-1 Numero di nodi n r =2 h-1 -1 Numero di nodi n s =2 h -1 n s /n = 2 h -1/(3 2 h-1 -1)  2/3 Albero completo di altezza h-2 nsns nrnr

Complessità di Heapify:caso peggiore T(n) = max(O(1),max(O(1),T(?) + O(1))  max(O(1),max(O(1),T(2n/ 3) + O(1))  T(2n/ 3) +  (1) T’(n) = T’(2n/ 3) +  (1) Proviamo ad applicare il Metodo Iterativo! T’(n) =  (log n)

Complessità di Heapify:caso peggiore T(n) = max(O(1),max(O(1),T(?) + O(1))  max(O(1),max(O(1),T(2n/ 3) + O(1))  T(2n/ 3) +  (1) Quindi T(n) = O (log n) Heapify impiega tempo proporzionale all’altezza dell’albero su cui opera !

Complessità di Heapify:caso migliore T(n) = T(?) + O(1) Nel caso migliore Heapify ad ogni chiamata ricorsiva, viene eseguito su un numero di nodi che è maggiore di 1/3 del numero di nodi correnti n. Cioè il numero di nodi n s del sottoalbero su cui Heapify è chiamato ricorsivamente è al più 1/3 n (o n s  1/3 n )

Complessità di Heapify:caso migliore T(n) = T(?) + O(1)  T(n/ 3) +  (1) T’(n) = T’(n/ 3) +  (1) Applicando il Metodo Iterativo! T’(n) =  (log n) quindi T(n) =  (log n)

Costruisci Heap: intuizioni Costruisci-Heap(A) : utilizza l’algoritmo Heapify, per inserire ogni elemento dell’array in uno Heap, risistemando sul posto gli elementi:  gli ultimi  n/2  elementi dell’array sono foglie, cioè radici di sottoalberi vuoti, quindi sono già degli Heap  è sufficiente inserire nello Heap solo i primi  n/2  elementi, utilizzando Heapify per ripristi- nare la proprietà Heap sul sottoalbero del nuovo elemento.

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i)

Costruisci Heap

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 6i = 6

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 6i = 6

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 6i = 6 Heap

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 5i = 5

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 5i = 5 Heap

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 4i = 4

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 4i = 4 Heap

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 3i = 3 Heap

Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) i = 2i = 2 Heap

Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) Costruisci Heap i = 1i =

Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) Costruisci Heap i = 1i =

Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) Costruisci Heap i = 1i =

Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) Costruisci Heap i = 1i =

Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) Costruisci Heap i = 1i =

Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i) Costruisci Heap i = 1i = Heap

Costruisci Heap Heap

Complessità di Costruisci Heap Costruisci-Heap(A) heapsize[A] = length[A] FOR i =  length[A]/2  DOWNTO 1 DO Heapify(A,i)

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n))) Poiché Heapify viene chiamata n/2 volte si potrebbe ipotizzare f(n) = O(n log n) e quindi T(n) = max(O(1), O(n log n)) = O(n log n) ma….

Complessità di Costruisci Heap Costruisci-Heap chiama Heapify n/2 volte su Heap di altezza 0 (non eseguito) 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

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n))) Costruisci-Heap chiama Heapify n/2 volte su Heap di altezza 0 (in reltà non eseguito) 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

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n)))

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n)))

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n))) x = 1/2  1

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n)))

Complessità di Costruisci Heap T(n) = max(O(1), O(?)) = max(O(1), O(f(n))) T(n) = max(O(1), O(n)) = O(n) Costruire uno Heap di n elementi è poco costoso, al più costa O(n) !

Heap Sort: intuizioni Heap-Sort : è una variazione di Select-sort in cui la ricerca dell’elemento massimo è facilitata dal mantenimento della sequenza in uno heap:  si costruisce uno Heap a partire dall’array non ordinato in input.  viene sfruttata la proprietà degli Heap per cui la radice A[1] dello Heap è sempre il massimo:  scandisce tutti gli elementi dell’array a partire dall’ultimo e ad ogni iterazione  la radice A[1] viene scambiata con l’elemento nell’ultima posizione corrente dello Heap  viene ridotta la dimensione dello Heap e  ripristinato lo Heap con Heapify

Heap Sort: intuizioni n 1 disordinati parzialmente ordinati heap n 1 costruisci heap max scambio + heapify n 1 max ordinati parzialmente ordinati heap i

Heap Sort Heap-Sort(A) Costruisci-Heap(A) FOR i = length[A] DOWNTO 2 DO /* elemento massimo in A[1] */ “scambia A[1] e A[i]” /* ripristina lo heap */ heapsize[A] = heapsize[A]-1 Heapify(A,1) Select-Sort(A) FOR i = length[A] DOWNTO 2 DO max = Findmax(A,i) “scambia A[max] e A[i]”

Heap Sort Heap-Sort(A) Costruisci-Heap(A) …

Heap Sort Heap-Sort(A) Costruisci-Heap(A) …

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 12 heapsize[A]=12

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 12 heapsize[A]=12

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = heapsize[A]=11

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = heapsize[A]=11

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 12 heapsize[A]=11

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 11 heapsize[A]=11

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = heapsize[A]=10

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 11 heapsize[A]=10

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = heapsize[A]=10

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = heapsize[A]=

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = heapsize[A]=9

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 9i = heapsize[A]=9

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 9i = heapsize[A]=8 28 9

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 9i = heapsize[A]=8

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 8i = heapsize[A]=8

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 8i = heapsize[A]=7

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 7i = heapsize[A]=7

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 7i = heapsize[A]=6

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 6i = heapsize[A]=6

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 6i = heapsize[A]=5

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 5i = heapsize[A]=5

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 5i = heapsize[A]=4

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 4i = heapsize[A]=4

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 4i = heapsize[A]=3

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 3i = heapsize[A]=3

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 3i = heapsize[A]=2

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 2i = heapsize[A]=2

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 2i = heapsize[A]=1

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 1i = heapsize[A]=1

Heap Sort Heap-Sort(A) … FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1) i = 1i = 1 heapsize[A]= L’array A ora è ordinato!

Heap Sort Heap-Sort(A) Costruisci-Heap(A) FOR i = length[A] DOWNTO 2 DO “scambia A[1] e A[i]” heapsize[A] = heapsize[A]-1 Heapify(A,1)

Complessità di Heap Sort Nel caso peggiore Heap-Sort chiama una volta Costruisci-Heap; n-1 volte Heapify sullo Heap corrente T(n) = max(O(n), (n-1)  max(O(1), T(Heapify)))

Complessità di Heap Sort Nel caso peggiore Heap-Sort chiama una volta Costruisci-Heap; n-1 volte Heapify sull’intero Heap. T(n) = max(O(n), (n-1)  max(O(1), T(Heapify))) = max(O(n), max(O(n), O(n log n))) T(n) = O(n log n)

HeapSort: conlusioni HeapSort Algoritmo di ordinamento sul posto per confronto che impiega tempo O(n log n). Algoritmo non immediato nè ovvio. Sfrutta le proprietà della struttura dati astratta Heap.

HeapSort: conlusioni HeapSort dimostra che: scegliere una buona rappresentazione per i dati spesso facilita la progettazione di buoni algoritmi; importante pensare a quale può essere una buona rappresentazione dei dati prima di implementare una soluzione.