Costruzione di uno heap
In questa pagina 4
Problema. Input: array di entry. Output: lo stesso array riorganizzato in modo da rappresentare uno heap (vedi HeapAlbero binario completo e sua altezza floor(log2 n); heap = albero completo con heap-order property; proprietà (radice minima, cammini non decrescenti); rappresentazione su array con level numbering; insert con up-heap bubbling, removeMin con down-heap bubbling, rimozione di una entry qualsiasi; invarianti e costi Theta(log n); esempio svolto.Heap →). Entrambe le soluzioni lavorano in loco (senza array aggiuntivi). L'up-heap e il down-heap bubbling sono quelli di HeapAlbero binario completo e sua altezza floor(log2 n); heap = albero completo con heap-order property; proprietà (radice minima, cammini non decrescenti); rappresentazione su array con level numbering; insert con up-heap bubbling, removeMin con down-heap bubbling, rimozione di una entry qualsiasi; invarianti e costi Theta(log n); esempio svolto.Heap →; per i conti sulle somme servono SommatorieIl simbolo di sommatoria, le sue proprietà (linearità, additività, cambio di indice) e le somme notevoli di Gauss e geometrica.Sommatorie → e la serie geometrica (Serie notevoli - geometrica, telescopica, armonicaLe serie di cui si conosce il carattere e da usare come termine di paragone: geometrica (converge a 1/(1-q) se |q|<1), telescopiche (somma b_1 - lim b_n, come Mengoli), armonica generalizzata (1/n^alpha converge se e solo se alpha>1).Serie notevoli - geometrica, telescopica, armonica →), e per le dimostrazioni per induzione Principio di induzionePer dimostrare una proprietà per ogni n basta il passo base e il passo induttivo da n a n+1.Principio di induzione →.
Top-down: inserimenti successivi
Definizione (costruzione top-down con inserimenti successivi). Si considera uno heap di un elemento e si inserisce con l'up-heap bubbling.
Esempio. Con : è uno heap; insert di lo fa salire sopra (); insert di sale fino alla radice ().
for j <- 2 to n do
up-heap bubbling a partire da P[j]Invariante (alla fine dell'iterazione ): rappresenta uno heap, è immutato.
Formula (costo della costruzione top-down). Costo. L'iterazione costa , quindi . È anche : se è in ordine decrescente ogni nuova chiave è minore di tutte le precedenti e sale fino alla radice, e
Quindi (anche
insertconsecutive in uno heap vuoto, vedi Esercizio 13 · costruzione di uno heap top-down e bottom-up).
Perché la disuguaglianza della somma. I termini con sono almeno (per pari sono ) e ciascuno vale almeno , perché il logaritmo è crescente (Esponenziale e logaritmoLa funzione esponenziale a^x (base positiva diversa da 1) e la sua inversa, il logaritmo in base a, con grafici e proprietà.Esponenziale e logaritmo →). Inoltre , che per grande è : il prodotto è . Con l'array decrescente ogni iterazione fa tanti scambi quanti il livello del nodo , cioè .
Esempio. : dopo : ; ( sale sopra ): ; : ; ( sopra ): ; ( sopra , poi stop): . Gli scambi sono stati , in tutto .
Bottom-up: dalle foglie verso la radice
Definizione (costruzione bottom-up). Le posizioni sono foglie e quindi già heap da un elemento. Si procede a ritroso sui nodi interni, "sistemando" ciascuno con il down-heap bubbling: ogni nodo ha come sottoalberi due heap già costruiti.
Esempio. Con si ha : sono foglie e si sistemano con il down-heap bubbling.
for j <- floor(n/2) downto 1 do
down-heap bubbling a partire da P[j]Invariante (alla fine dell'iterazione ): rappresenta una foresta di heap, è immutato. Alla fine e è uno heap.
Formula (costo della costruzione bottom-up). Costo. Sia . Il down-heap da un nodo al livello () costa (al più la distanza dalle foglie), e al livello ci sono al più nodi. Il costo totale è
Si dimostra per induzione che : per è ; passando da a si somma e si ottiene . (Nel corso si dimostra la limitazione più debole , che basta.) Dunque il costo è , perché .
Come si arriva alla somma . Un nodo al livello ha sotto di sé al massimo livelli, quindi il suo down-heap fa al più scambi. Con la sostituzione (distanza dalle foglie) si ha , da cui . Il punto chiave è che il peso cresce linearmente mentre il numero di nodi con quella distanza si dimezza a ogni passo verso l'alto: la serie converge (vedi Criteri del rapporto e della radice per le seriePer una serie a termini positivi, se il limite di a_(n+1)/a_n (criterio del rapporto) o di radice n-esima di a_n (criterio della radice) è L < 1 la serie converge, se è L > 1 diverge; con L = 1 il criterio non dice nulla.Criteri del rapporto e della radice per le serie →: il rapporto tra termini consecutivi tende a ) e la somma resta limitata da una costante. Controllo con : , coerente con la formula . Ed è : servono almeno iterazioni. .
Perché il bottom-up è più veloce. Nel top-down le iterazioni costose sono molte: i nodi del livello costano ciascuno (più sono numerosi, più costano). Nel bottom-up i livelli più numerosi (vicini alle foglie) costano poco, , e solo i pochi nodi in alto costano .
Grafico interattivo: Scambi al caso peggiore nella costruzione di uno heap con n elementi: top-down su array decrescente, (n+1)·⌊log₂n⌋ − 2^(⌊log₂n⌋+1) + 2 (34 per n = 15, 258 per n = 63, 1538 per n = 255), bottom-up al più n − 1 (somma delle altezze dei nodi: 11, 57 e 247 se n = 2^k − 1)
Numero massimo di scambi del bottom-up, per (albero perfetto, ): foglie a distanza dal fondo, nodi con al più scambio, con al più , con al più : , contro i del top-down sull'array decrescente. Per questo il costo è lineare e non .
Esempio. (, ):
| Dopo | Array |
|---|---|
| 6 | () |
| 5 | () |
| 4 | invariato () |
| 3 | () |
| 2 | () |
| 1 | () |
Un altro esempio (da un tema d'esame): con : : ha come unico figlio , scambio, ; : ha figli e , il minore è , scambio, ; : ha figli e , minore , scambio (ora è in posizione con figli e ), minore , scambio, ( scende scambiando con , poi con ). Totale scambi.
Altre costruzioni
Fusione di due heap come alberi (non necessariamente completi, altezze ) in tempo : si rimuove una foglia da , si crea una nuova radice con la entry di e come figli e , poi si esegue il down-heap dalla radice.
Definizione (heap sort). Costruzione bottom-up e poi
removeMinda : (vedi Algoritmi di ordinamentoSelection sort e insertion sort (quadratici, con invarianti), merge sort (divide et impera, Theta(n log n)), quick sort (caso pessimo quadratico, medio n log n), heap sort (in loco, Theta(n log n)), ordinamento senza confronti per chiavi intere in un intervallo piccolo, limite inferiore Omega(n log n) per gli algoritmi basati su confronti.Algoritmi di ordinamento →).
Esempio. Con chiavi: costruzione bottom-up e poi removeMin, ciascuno con circa scambi al più.
Errori comuni
- Eseguire il bottom-up partendo dalla fine dell'array (le foglie sono già heap): si parte da .
- Percorrere in avanti nel bottom-up: il down-heap richiede che i sottoalberi siano già heap.
- Dire che il bottom-up costa perché ogni down-heap è : la somma dei costi per livello è lineare.
- Dimenticare il caso peggiore del top-down: array in ordine decrescente.
Versione ripasso
- Problema: dato l'array di entry, riorganizzarlo come heap, in loco (vedi HeapAlbero binario completo e sua altezza floor(log2 n); heap = albero completo con heap-order property; proprietà (radice minima, cammini non decrescenti); rappresentazione su array con level numbering; insert con up-heap bubbling, removeMin con down-heap bubbling, rimozione di una entry qualsiasi; invarianti e costi Theta(log n); esempio svolto.Heap →).
- Top-down: si esegue
for j <- 2 to n: up-heap bubbling da P[j]. Invariante: alla fine di ogni iterazione è uno heap e è immutato. Costo . - top-down: con in ordine decrescente ogni nuova chiave sale fino alla radice, e . Quindi (vedi Esercizio 13 · costruzione di uno heap top-down e bottom-up).
- Esempio top-down: diventa con scambi.
- Bottom-up: le posizioni sono foglie, già heap da un elemento. Si esegue
for j <- floor(n/2) downto 1: down-heap bubbling da P[j]. Invariante: alla fine di ogni iterazione è una foresta di heap; alla fine e è uno heap. - Costo bottom-up: con , al livello ci sono al più nodi, ciascuno con costo . Il totale è . Per induzione , quindi ; inoltre . Quindi .
- Perché il bottom-up è più veloce: i livelli più numerosi, vicini alle foglie, costano poco; nel top-down i nodi del livello costano ciascuno.
- Scambi per : il bottom-up fa al più scambi (), il top-down su array decrescente fa .
- Esempio bottom-up, : diventa .
- Esempio da tema d'esame: con bottom-up diventa , con scambi.
- Fusione di due heap-albero in : si rimuove una foglia da , la si mette in una nuova radice con figli e , poi si esegue il down-heap dalla radice.
- Heap sort: bottom-up più
removeMinda , in totale (vedi Algoritmi di ordinamentoSelection sort e insertion sort (quadratici, con invarianti), merge sort (divide et impera, Theta(n log n)), quick sort (caso pessimo quadratico, medio n log n), heap sort (in loco, Theta(n log n)), ordinamento senza confronti per chiavi intere in un intervallo piccolo, limite inferiore Omega(n log n) per gli algoritmi basati su confronti.Algoritmi di ordinamento →). - Errori tipici: bottom-up partendo da o percorrendo in avanti; credere che il bottom-up costi ; dimenticare il caso decrescente del top-down.