Salta al contenuto
Note per Studenti Esercizio 12 · inserimenti e rimozioni in uno heap

Esercizio 12inserimenti e rimozioni in uno heap

Esame
In questa pagina 7

Testo (parti 1 di vari scritti: 24/06/2026, 10/09/2026, 30/01/2026, 09/09/2025 e un esempio di tema d'esame). Negli array che seguono sono indicate solo le chiavi, con indicizzazione da 11; ogni array rappresenta un min-heap.

  1. P=[2,5,4,9,8,7]P = [2, 5, 4, 9, 8, 7] con 66 entry. Disegnare l'albero corrispondente e scrivere l'array dopo insert(3).
  2. P=[3,6,5,10,8,12,9]P = [3, 6, 5, 10, 8, 12, 9]. Disegnare l'albero, eseguire insert(4) e scrivere l'array; poi eseguire removeMin() e scrivere l'array finale.
  3. P=[2,6,4,9,8,5,7]P = [2, 6, 4, 9, 8, 5, 7]. Disegnare l'albero e mostrare l'array dopo removeMin().
  4. P=[5,10,7,12,11,8]P = [5, 10, 7, 12, 11, 8]. Disegnare l'albero e far vedere l'array dopo insert(3).
  5. Una coda con priorità PP, implementata con uno heap e inizialmente vuota, riceve nell'ordine insert(5), insert(3), insert(6), insert(4), insert(7), insert(2), removeMin(). Disegnare lo heap risultante (solo le chiavi).

Richiami

Con indici da 11: figli di P[i]P[i] in P[2i]P[2i] e P[2i+1]P[2i+1], padre in P[⌊i/2⌋]P[\lfloor i/2 \rfloor] (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 →).

  • insert(k): kk in P[last+1]P[\text{last}+1] poi up-heap: finché ha un padre con chiave maggiore, si scambia con il padre.
  • removeMin(): si restituisce P[1]P[1]; si porta P[last]P[\text{last}] in P[1]P[1] e si accorcia di uno; poi down-heap: finché ha un figlio con chiave minore, si scambia con il figlio di chiave minima.

1. P=[2,5,4,9,8,7]P = [2, 5, 4, 9, 8, 7], insert(3)

        2
      /   \
     5     4
    / \   /
   9   8 7

33 va in posizione 77, figlio destro di P[3]=4P[3] = 4. Padre 4>34 > 3: scambio, 33 sale in posizione 33: [2,5,3,9,8,7,4][2, 5, 3, 9, 8, 7, 4]. Padre P[1]=2<3P[1] = 2 < 3: stop.

Risultato: [2,5,3,9,8,7,4][2, 5, 3, 9, 8, 7, 4].

2. P=[3,6,5,10,8,12,9]P = [3, 6, 5, 10, 8, 12, 9], insert(4) poi removeMin()

Albero: radice 33; figli 6,56, 5; nipoti 10,810, 8 (sotto 66) e 12,912, 9 (sotto 55).

insert(4): 44 in posizione 88 (figlio sinistro di P[4]=10P[4] = 10). 10>410 > 4: scambio, 44 in posizione 44: [3,6,5,4,8,12,9,10][3, 6, 5, 4, 8, 12, 9, 10]. Padre P[2]=6>4P[2] = 6 > 4: scambio, 44 in posizione 22: [3,4,5,6,8,12,9,10][3, 4, 5, 6, 8, 12, 9, 10]. Padre P[1]=3<4P[1] = 3 < 4: stop. Array dopo insert: [3,4,5,6,8,12,9,10][3, 4, 5, 6, 8, 12, 9, 10].

removeMin(): si restituisce 33. L'ultima entry (1010) va in radice: [10,4,5,6,8,12,9][10, 4, 5, 6, 8, 12, 9]. Figli di 1010: 44 e 55, il minore è 44: scambio →[4,10,5,6,8,12,9]\to [4, 10, 5, 6, 8, 12, 9]. Figli di 1010 in posizione 22: P[4]=6P[4] = 6 e P[5]=8P[5] = 8, minore 6<106 < 10: scambio →[4,6,5,10,8,12,9]\to [4, 6, 5, 10, 8, 12, 9]. In posizione 44 non ci sono figli (2⋅4=8>72 \cdot 4 = 8 > 7).

Risultato: [4,6,5,10,8,12,9][4, 6, 5, 10, 8, 12, 9].

3. P=[2,6,4,9,8,5,7]P = [2, 6, 4, 9, 8, 5, 7], removeMin()

Albero: radice 22; figli 6,46, 4; sotto 66: 9,89, 8; sotto 44: 5,75, 7. È un heap valido (ogni nodo ≤\le i figli).

Si restituisce 22; l'ultima entry (77) va in radice: [7,6,4,9,8,5][7, 6, 4, 9, 8, 5]. Figli 66 e 44: minore 44, scambio →[4,6,7,9,8,5]\to [4, 6, 7, 9, 8, 5]. Il 77 è in posizione 33 con figlio P[6]=5<7P[6] = 5 < 7 (non c'è P[7]P[7]): scambio →[4,6,5,9,8,7]\to [4, 6, 5, 9, 8, 7]. Posizione 66 senza figli.

Risultato: [4,6,5,9,8,7][4, 6, 5, 9, 8, 7].

4. P=[5,10,7,12,11,8]P = [5, 10, 7, 12, 11, 8], insert(3)

Albero: radice 55; figli 10,710, 7; sotto 1010: 12,1112, 11; sotto 77: 88. 33 va in posizione 77 (figlio destro di P[3]=7P[3] = 7). 7>37 > 3: scambio →[5,10,3,12,11,8,7]\to [5, 10, 3, 12, 11, 8, 7] (33 in posizione 33). Padre P[1]=5>3P[1] = 5 > 3: scambio →[3,10,5,12,11,8,7]\to [3, 10, 5, 12, 11, 8, 7] (33 in posizione 11): radice, stop.

Risultato: [3,10,5,12,11,8,7][3, 10, 5, 12, 11, 8, 7].

5. Sequenza di operazioni su heap vuoto

Operazione Array dopo
insert(5) [5][5]
insert(3) [3,5][3, 5] (3<53 < 5 sale)
insert(6) [3,5,6][3, 5, 6]
insert(4) [3,4,6,5][3, 4, 6, 5] (44 in pos. 4, padre 5>45 > 4 scambio; padre 3<43 < 4)
insert(7) [3,4,6,5,7][3, 4, 6, 5, 7] (7>47 > 4, nessuno scambio)
insert(2) [2,4,3,5,7,6][2, 4, 3, 5, 7, 6] (22 in pos. 6, padre 66, poi 33, arriva in radice)
removeMin() →2\to 2 [3,4,6,5,7][3, 4, 6, 5, 7]

Ultimo passo: l'ultima entry (66) va in radice, [6,4,3,5,7][6, 4, 3, 5, 7]; figli 4,34, 3: minore 33, scambio →[3,4,6,5,7]\to [3, 4, 6, 5, 7]; in posizione 33 non ci sono figli (6>56 > 5).

Albero finale: radice 33; figli 44 e 66; sotto 44: 55 e 77.

(Tutti gli array di questo esercizio sono stati verificati eseguendo un'implementazione dello heap.)

Errori comuni

  • Nel down-heap scambiare con il figlio sinistro invece che con il minore tra i due.
  • In removeMin portare in radice un'entry qualunque invece dell'ultima (si perde la completezza).
  • Non fermare il down-heap quando P[i]≤P[i] \le entrambi i figli, o proseguire oltre le foglie.
  • Dimenticare di aggiornare last\text{last} (numero di entry) dopo insert/removeMin.

Versione ripasso

Testo. Min-heap (solo chiavi, indici da 1): (1) [2,5,4,9,8,7][2,5,4,9,8,7], insert(3); (2) [3,6,5,10,8,12,9][3,6,5,10,8,12,9], insert(4) e poi removeMin(); (3) [2,6,4,9,8,5,7][2,6,4,9,8,5,7], removeMin(); (4) [5,10,7,12,11,8][5,10,7,12,11,8], insert(3); (5) heap vuoto con insert 5,3,6,4,7,25,3,6,4,7,2 e removeMin().

Teoria collegata