ESTRAI-MIN() { minimo = FH->min; if(FH->min != NULL) for(ogni figlio x di FH->min) togli x dala lista dei figli di min; aggiungi x alla lista delle radici di FH; x->ppadre = NULL; FH->nalberi = FH->nalberi + 1; if(FH->nnodi == 1) FH->min = NULL; FH->nalberi = FH->nalberi - 1; else FH->min = FH->min->pdestro; CONSOLIDATE(); <- funzione di ristrutturazione dello Heap FH->nnodi = FH->nnodi - 1; return minimo; }
La ESTRAI-MIN() accede direttamente al minimo grazie al campo min dello Heap, ``promuove'' ogni suo figlio a radice; se il minimo era l'unico nodo mette il campo min a NULL, altrimenti gli assegna il suo adiacente destro (che non necessariamente è realmente il nuovo minimo) ed esegue la funzione di restaurazione; infine viene appropriatamente aggiornato il campo contatore dei numeri di nodi dello Heap e viene ritornato il nodo con chiave minima. Chiaramente se lo Heap è vuoto viene ritornato NULL.
La CONSOLIDATE() ha il compito di ricompattere il più possibile gli alberi; tale operazione eseguirà ripetutamente i seguenti due passi:
R[ ]: vettore di puntatori alle radici (init: NULL), R[i] punta all'ultima radice di grado i incontrata x, y: puntatori alle radici correnti g: contiene il grado dell'ultima radice considerata CONSOLIDATE() { R[i] = NULL per ogni i; for(ogni nodo nd della lista della radici di FH) g = nd->grado; x = nd; while(R[g] != NULL) y = R[g]; if(x->chiave > y->chiave) swap(x, y); LINK(y, x); R[g] = NULL; g = g+1; R[g] = x; FH->min = NULL; for(ogni i fino alla fine di R[ ]) if (R[i] != NULL) aggiungi R[i] alla lista delle radici; if(FH->min == NULL)oppure(R[i]->chiave < FH->min->chiave) FH->min = R[i]; }
Per ogni radice dello Heap controlla se è stata precedentemente incontrata
un'altra radice con lo stesso grado: in caso affermativo quella con chiave minore
viene ``linkata'' all'altra (con la chiamata della funzione LINK), il grado
della radice-padre viene incrementato e viene effettuato nuovamente lo stesso
controllo. In caso negativo invece, la radice viene memorizzata nel vettore
alla posizione
, dove
è il grado della radice stessa.
Infine viene aggiornato il campo min e ricreata la lista delle radici:
viene scandito tutto il vettore inserendo una ad una ogni radice presente in
esso.
La funzione LINK serve per fondere due alberi in uno; la radice di uno dei due
(quella con chiave minore) diventa un nodo figlio della radice dell'altro:
LINK(y, x) { togli y dalla lista delle radici di FH; aggiungi y alla lista dei figli di x; x->grado = x->grado + 1; y->marcato = false; }
![]() |
Per il calcolo del costo della ESTRAI-MIN è indispensabile assumere che esiste un
limite superiore al grado massimo di un nodo qualsiasi dello Heap di
Fibonacci; questo fatto verrà dimostrato in seguito (sottosezione 2.10).
Affinchè il costo della ESTRAI-MIN sia ottimale è ovvio che la dimensione di
debba essere anch'essa ottimale in quanto tale vettore viene più
volte scandito e questo fatto potrebbe fare aumentare il costo totale; la sua
dimensione sará
che è proprio il grado massimo che una radice
può avere.
Dimostriamo ora che il costo ammortizzato della ESTRAI-MIN è : un
contributo pari a
è dato dal ciclo che promuove a radice tutti gli
figli del nodo minimo; vi sono poi l'inizializzazione del vettore
(all'inizio della CONSILIDATE) e la ricreazione della lista delle radici dello
Heap (alla fine della CONSOLIDATE) che consitono entrambe nello scandire
e che
quindi portano un contributo pari anch'esso a
.
Resta ora da considerare la parte centrale della funzione CONSOLIDATE, quella
incaricata di trovare e fondere gli alberi di uguale dimensione; il ciclo in
questione opera una scansione della lista delle radici: tale lista è al più
dal momento che è formata dalla vecchia lista delle radici (
)
e dai figli del nodo con chiave minima (D(n)); inoltre ad essa è stato tolto il
minimo (-1). Quindi il costo reale totale in questo caso è
.
Trovato il costo reale non resta che il calcolo del potenziale per avere al termine
il costo ammortizzato.
Il potenziale prima:
e dopo:
Notiamo subito che il potenziale di è minore o uguale a quello di
in quanto il numero di radici dopo la ristrutturazione dello Heap è
diventato al più
(esattamente come il numero di radici in uno
Heap Binomiale).
Il costo ammortizzato come al solito è:
sostituendo i due potenziali:
dal momento che è stato assunto come
, si ha: