Salta al contenuto
Note per Studenti Costruzione di uno heap

Costruzione di uno heap

In questa pagina 4

Problema. Input: array P[1..n]P[1..n] 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).

Top-down: n−1n-1 inserimenti successivi

Si considera P[1]P[1] uno heap di un elemento e si inserisce P[2],P[3],…,P[n]P[2], P[3], \dots, P[n] con l'up-heap bubbling.

for j <- 2 to n do
    up-heap bubbling a partire da P[j]

Invariante (alla fine dell'iterazione jj): P[1..j]P[1..j] rappresenta uno heap, P[j+1..n]P[j+1..n] è immutato.

Costo. L'iterazione jj costa O(log⁡j)O(\log j), quindi O(∑j=2nlog⁡j)=O(nlog⁡n)O\big(\sum_{j=2}^{n} \log j\big) = O(n \log n). È anche Ω(nlog⁡n)\Omega(n \log n): se PP è in ordine decrescente ogni nuova chiave è minore di tutte le precedenti e sale fino alla radice, e

∑j=⌊n/2⌋nlog⁡2j ≥ n2log⁡2⌊n2⌋∈Ω(nlog⁡n).\sum_{j=\lfloor n/2 \rfloor}^{n} \log_2 j \ \ge\ \frac n2 \log_2 \Big\lfloor \frac n2 \Big\rfloor \in \Omega(n \log n).

Quindi Θ(nlog⁡n)\Theta(n \log n) (anche nn insert consecutive in uno heap vuoto, vedi Esercizio 13 · costruzione di uno heap top-down e bottom-up).

Esempio. P=[2,10,27,9,11,13,5]P = [2, 10, 27, 9, 11, 13, 5]: dopo j=2,3j = 2,3: [2,10,27][2, 10, 27]; j=4j = 4 (99 sale sopra 1010): [2,9,27,10][2, 9, 27, 10]; j=5j = 5: [2,9,27,10,11][2, 9, 27, 10, 11]; j=6j = 6 (1313 sopra 2727): [2,9,13,10,11,27][2, 9, 13, 10, 11, 27]; j=7j = 7 (55 sopra 1313, poi 5>25 > 2 stop): [2,9,5,10,11,27,13][2, 9, 5, 10, 11, 27, 13].

Bottom-up: dalle foglie verso la radice

Le posizioni ⌊n/2⌋+1,…,n\lfloor n/2 \rfloor + 1, \dots, n 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.

for j <- floor(n/2) downto 1 do
    down-heap bubbling a partire da P[j]

Invariante (alla fine dell'iterazione jj): P[j..n]P[j..n] rappresenta una foresta di heap, P[1..j−1]P[1..j-1] è immutato. Alla fine j=1j = 1 e P[1..n]P[1..n] è uno heap.

Costo. Sia h=⌊log⁡2n⌋h = \lfloor \log_2 n \rfloor. Il down-heap da un nodo al livello ii (0≤i≤h−10 \le i \le h-1) costa O(h−i)O(h - i) (al più la distanza dalle foglie), e al livello ii ci sono al più 2i2^i nodi. Il costo totale è

O(∑i=0h−12i(h−i))=O(2h∑i=0h−1h−i2h−i)=O(2h∑ℓ=1hℓ2ℓ).O\Big( \sum_{i=0}^{h-1} 2^i (h - i) \Big) = O\Big( 2^h \sum_{i=0}^{h-1} \frac{h - i}{2^{h-i}} \Big) = O\Big( 2^h \sum_{\ell=1}^{h} \frac{\ell}{2^\ell} \Big).

Si dimostra per induzione che ∑ℓ=1hℓ2ℓ=2−h+22h<2\sum_{\ell=1}^{h} \frac{\ell}{2^\ell} = 2 - \frac{h+2}{2^h} < 2: per h=1h = 1 è 12=2−32\frac12 = 2 - \frac32; passando da hh a h+1h+1 si somma h+12h+1\frac{h+1}{2^{h+1}} e si ottiene 2−2(h+2)−(h+1)2h+1=2−h+32h+12 - \frac{2(h+2) - (h+1)}{2^{h+1}} = 2 - \frac{h+3}{2^{h+1}}. (Nel corso si dimostra la limitazione più debole ∑ℓ(1/2)ℓ<3\sum \ell (1/2)^\ell < 3, che basta.) Dunque il costo è O(2h)=O(n)O(2^h) = O(n), perché 2h≤n2^h \le n. Ed è Ω(n)\Omega(n): servono almeno ⌊n/2⌋\lfloor n/2 \rfloor iterazioni. Θ(n)\Theta(n).

Perché il bottom-up è più veloce. Nel top-down le iterazioni costose sono molte: i 2i2^i nodi del livello ii costano Θ(i)\Theta(i) ciascuno (più sono numerosi, più costano). Nel bottom-up i livelli più numerosi (vicini alle foglie) costano poco, Θ(h−i)\Theta(h - i), e solo i pochi nodi in alto costano Θ(log⁡n)\Theta(\log n).

Esempio. P=[2,10,27,9,11,13,5,30,18,1,14,15,6]P = [2, 10, 27, 9, 11, 13, 5, 30, 18, 1, 14, 15, 6] (n=13n = 13, ⌊n/2⌋=6\lfloor n/2 \rfloor = 6):

Dopo jj Array
6 [2,10,27,9,11,6,5,30,18,1,14,15,13][2, 10, 27, 9, 11, 6, 5, 30, 18, 1, 14, 15, 13] (13↔613 \leftrightarrow 6)
5 [2,10,27,9,1,6,5,30,18,11,14,15,13][2, 10, 27, 9, 1, 6, 5, 30, 18, 11, 14, 15, 13] (11↔111 \leftrightarrow 1)
4 invariato (9<30,189 < 30, 18)
3 [2,10,5,9,1,6,27,30,18,11,14,15,13][2, 10, 5, 9, 1, 6, 27, 30, 18, 11, 14, 15, 13] (27↔527 \leftrightarrow 5)
2 [2,1,5,9,10,6,27,30,18,11,14,15,13][2, 1, 5, 9, 10, 6, 27, 30, 18, 11, 14, 15, 13] (10↔110 \leftrightarrow 1)
1 [1,2,5,9,10,6,27,30,18,11,14,15,13][1, 2, 5, 9, 10, 6, 27, 30, 18, 11, 14, 15, 13] (2↔12 \leftrightarrow 1)

Un altro esempio (da un tema d'esame): P=[11,9,7,13,3,4]P = [11, 9, 7, 13, 3, 4] con ⌊6/2⌋=3\lfloor 6/2 \rfloor = 3: j=3j = 3: [11,9,4,13,3,7][11, 9, 4, 13, 3, 7]; j=2j = 2: [11,3,4,13,9,7][11, 3, 4, 13, 9, 7]; j=1j = 1: [3,9,4,13,11,7][3, 9, 4, 13, 11, 7] (1111 scende scambiando con 33, poi con 99).

Altre costruzioni

Fusione di due heap come alberi (non necessariamente completi, altezze h1,h2h_1, h_2) in tempo O(h1+h2)O(h_1 + h_2): si rimuove una foglia vv da T1T_1, si crea una nuova radice con la entry di vv e come figli T1T_1 e T2T_2, poi si esegue il down-heap dalla radice.

Heap sort. Costruzione bottom-up Θ(n)\Theta(n) e poi nn removeMin da Θ(log⁡n)\Theta(\log n): Θ(nlog⁡n)\Theta(n \log n) (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 comuni

  • Eseguire il bottom-up partendo dalla fine dell'array (le foglie sono già heap): si parte da ⌊n/2⌋\lfloor n/2 \rfloor.
  • Percorrere jj in avanti nel bottom-up: il down-heap richiede che i sottoalberi siano già heap.
  • Dire che il bottom-up costa nlog⁡nn \log n perché ogni down-heap è log⁡n\log n: la somma dei costi per livello è lineare.
  • Dimenticare il caso peggiore del top-down: array in ordine decrescente.

Versione ripasso

Esercizi su questo argomento

Teoria collegata