Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
1
Code a priorità (Heap) Definizione
Heapify (mantenimento coda a priorità) Costruire un Heap Insert, Maximum e Extract-Max
2
Coda a priorità (Heap) Una coda a priorità può essere rappresentato da un albero binario completo. La chiave del padre è sempre maggiore di quella dei figli: key(i) ≤ key(parent(i)) . Albero binario completo: Sono riempiti tutti i livelli eccetto possibilmente l’ultimo. Altezza=Θ(log(n)) Coda a priorità: Il nodo a maggiore priorità (con la chiave più grande) sta in cima. Nota: si può ragionare in maniera analoga quando si pone che key(i) ≥ key(parent(i)). 16 10 14 8 7 9 3 2 4 1
3
Heap tramite un Array Una coda a priorità può essere implementato tramite un’array (A). A[PARENT(i)] ≥ A[i]. 1 16 3 2 10 PARENT(j) return 14 4 5 6 7 LEFT(i) return 2i 8 7 9 3 8 9 10 2 4 1 RIGHT(i) return 2i+1 heap-size[A] length[A] 1 2 3 4 5 6 7 8 9 10 n A 16 14 10 8 7 9 3 2 4 1 …
4
Heapify (mantenimento coda a priorità)
Si sistema l’elemento A[i]: si suppone gli alberi con radice LEFT(i) e RIGHT(i) siano degli Heap. A[i] LEFT[i] RIGHT[i] HEAP HEAP
5
Heapify (mantenimento coda a priorità)
Si sistema l’elemento A[i]: si suppone gli alberi con radice LEFT(i) e RIGHT(i) siano degli Heap. HEAPIFY(A,i) // sistema A[i] nel Heap l ← LEFT(i) // figlio sx r ← RIGHT(i) // figlio dx if l ≤ heap-size[A] and A[l] > A[i] // cerca il maggiore fra padre e then magg ← l // i due figli (se ci sono…) else magg ← i if r ≤ heap-size[A] and A[r] > A[magg] then magg ← r if magg ≠ i // il magg è uno dei due figli… then scambia A[i] ↔ A[magg] HEAPIFY(A,magg)
6
Esempio Heapify All’inizio si chiama HEAPIFY(A,2) i i 16 16 10 4 10 14
3 3 2 2 10 4 i 10 14 4 5 6 7 4 5 6 7 4 i 7 9 3 14 7 9 3 8 9 8 9 10 10 2 8 1 2 8 1
7
Esempio Heapify Il costo in termine di tempo è nel caso peggio l’altezza dell’albero. O(h) = O(log(n)) 1 16 3 2 10 14 4 5 6 7 8 7 9 3 i 8 9 10 2 4 1
8
Costruire l’Heap BUILD-HEAP(A) // strategia bottom-up: dal basso verso l’alto heap-size[A] ← length[A] // for i ← length[A]/2 downto 1 // dalla metà in su do HEAPIFY(A,i) // sotto la metà sono tutte foglie Il costo di HEAPIFY è O(log(n)) e viene chiamato O(n) volte. Quindi un limite del caso peggiore è O(n log(n)). In realtà, il caso peggiore può essere stimato come O(n). =2 Rappresenta il massimo numero di sottoalberi pieni ad altezza h (avendo a disposizione n elementi)
9
Esempio costruzione Heap
1 2 3 4 5 6 7 8 9 10 A 4 1 3 2 16 9 10 14 8 7 Foglie Si comincia da qua 1 1 4 4 3 3 2 2 3 3 1 1 4 5 6 7 4 5 6 7 i 2 i 16 9 10 2 16 9 10 8 9 8 9 10 10 14 8 7 14 8 7
10
Esempio costruzione Heap
Strategia button-up: dal basso verso l’alto si chiama HEAPIFY su tutte i nodi interni. 1 1 4 4 3 3 2 2 10 3 i 1 i 1 4 5 6 7 4 5 6 7 14 16 9 3 14 16 9 10 8 9 8 9 10 10 2 8 7 2 8 7
11
Esempio costruzione Heap
Strategia button-up: dal basso verso l’alto si chiama HEAPIFY su tutte i nodi interni. 1 1 i 16 4 3 3 2 2 10 3 14 16 4 5 6 7 4 5 6 7 8 7 9 3 14 7 9 10 8 9 8 9 10 10 2 4 1 2 8 1
12
Altre operazioni MAXIMUM(A): ritorna l’elemento a massima priorità, ossia quello in cima. EXTRACT-MAX(A): estrae l’elemento a massima priorità, successivamente l’Heap andrebbe sistemato INSERT(A): inserisce un nuovo elemento nel Heap.
13
MAXIMUM e EXTRACT-MAX MAXIMUM(A) ha un tempo di esecuzione costante, O(1) MAXIMUM(A) // restituisci l’elem. a magg. priorità, return A[1] // ossia quello in cima EXTRACT-MAX(A) ha un tempo di esecuzione O(log(n)), dovuto alla chiamata HEAPIFY(). EXTRACT-MAX(A) // Estrae elemento a maggiore priorità if heap-size[A] < 1 // heap vuoto? then error “heap underflow” max← A[1] // memorizza elem. In cima A[1]← A[heap-size[A]] // metti l’ultimo elemento in cima heap-size[A]← heap-size[A] – 1 // heap diminuisce di 1 elem. HEAPIFY(A,1) // HEAPIFY sul 1° elem. return max // restituisci l’elem. a magg. priorità
14
HEAP-INSERT HEAP-INSERT(A, KEY) ha un tempo di esecuzione O(log(n)), nel caso peggiore si risale l’albero dalla foglia alla radice. HEAP-INSERT(A, key) // Inserisci elemento nell’Heap heap-size[A]← heap-size[A] // aumenta Heap di 1 elemento i← heap-size[A] // inizia dall’elem. inserito (ultimo) while i > 1 and A[PARENT(i)]<key // il nuovo elem. Viene fatto do A[i] ← A[PARENT(i)] // risalire… i← PARENT(i) A[i] ← key // fino a trovare il suo posto
15
Inserimento in un Heap HEAP-INSERT(A, 15) key=15
L’Heap viene aumentato di un elemento. Si procede poi a risalire l’albero per trovare il suo posto. 1 1 16 16 3 3 2 2 10 3 14 14 4 5 6 7 4 5 6 7 8 i 7 9 3 8 7 9 10 8 9 8 9 11 10 11 10 2 4 1 7 2 4 1 8 i Nuovo elemento key = 15
16
Inserimento in un Heap HEAP-INSERT(A, 15) key=15
L’Heap viene aumentato di un elemento. Si procede poi a risalire l’albero per trovare il suo posto. 1 1 16 16 3 3 2 2 10 3 15 14 i 4 5 6 7 4 5 6 7 8 14 9 3 8 14 9 10 8 9 10 11 8 9 10 11 2 4 1 7 2 4 1 7
17
Considerazioni La struttura dati Heap gestisce una coda a priorità.
Viene estratto l’elemento a maggiore priorità (es. quello con chiave maggiore) Si può invertire la relazione con il padre, se key(i) ≥ key(parent(i)). In questo caso l’elemento a maggiore priorità è l’elemento più piccolo Heap-sort: algoritmo di ordinamento che usa un Heap. Si estrae ogni volta l’elemento più piccolo fino ad ottenere un vettore ordinato. Tempo O(n log(n)).
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.