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: