universityin-classsubject-2101
2023-10-10
Algoritmi
Heap (Priority Queue):
Insert(k)
conk
prioritàMax()
Extract-Max()
Delete(x)
conx
elementoIncrease-Key(x, k)
conx
elemento ek
priorità
la stessa struttura esiste anche al contrario (dove i valori più piccoli hanno priorità)
Tutti i metodi hanno complessità Max()
che ha complessità
A differenza dell’albero binario classico, l’heap è un albero binario (quasi) completo: tutti i livelli sono completi (ovvero sono presenti tutti i nodi) ad eccezione dell’ultimo che può non contenere degli elementi. Se però mancano degli elementi, allora quelli presenti sono allineati a sinistra.
Nel Max-Heap, ogni nodo ha la priorità più alta dei nodi figli.
In un albero completo, il numero di foglie è
Heapify(x)
: crea un heap a partire dal nodo x
. È utile quando non si è sicuri che l’heap a partire da x
sia valido, nonostante i due figli lo siano (se non lo sono, l’algoritmo non funziona).
Si scambiano le chiavi del nodo x
con quella del nodo figlio con chiave maggiore. Si richiama l’heapify
ricorsivamente sul nodo figlio.
// O(log n)
void heapify(Node* x) {
Node* left = node->left;
Node* right = node->right;
Node* max = x;
if (left != nullptr && left->key > max->key)
max = left;
if (right != nullptr && right->key > max->key)
max = right;
if (max != x) {
swap(x->key, max->key):
heapify(max);
}
}
Nell’heap è presente un puntatore detto HeapSize
che punta al nodo più a destra dell’ultimo livello
void extractMax() {
swap(root->key, heapSize->key);
removeHeapSize(); // viene staccato il nodo puntato dall'heapSize dall'albero e viene aggiornato l'heapSize.
heapify(root);
}
L’HeapSize
viene approfondito nelle sezioni successive
void increaseKey(Node* x, Priority k) {
x->key = k;
while (x != root && x->parent->key < x->key) {
swap(x->key, x->parent->key);
x = x->parent;
}
}
void insert(Priority k) {
// aggiunge un nodo in corrispondenza dell'heapsize, incrementandolo
Node* x = createNodeAtHeapSize(-INFINITY); // pseudocodice -infinito
increaseKey(x, k);
}
void delete(Node *x) {
swap(x->key, heapSize->key);
removeHeapSize();
heapify(x);
}
In realtà l’heap non viene implementato mediante un albero, bensì utilizzando un array.