Heap, heapsort e code a priorità Paolo Camurati Dip. Automatica e Informatica Politecnico di Torino
Heap Definizione: albero binario con proprietà strutturale: quasi completo (tutti i livelli completi, tranne eventualmente l ultimo, riempito da SX a DX) quasi bilanciato proprietà funzionale: i r key(parent(i)) key(i) conseguenza: chiave max nella radice. A.A. 24/25 Heap, heapsort e code a priorità 2
A.A. 24/25 Heap, heapsort e code a priorità 3 Operazioni: Heapify(A,i) BuildHeap(A) HeapSort(A).
Code a priorità Definizione: struttura dati per mantenere un set S di n elementi a ciascuno dei quali è associata una priorità. Operazioni: insert(s, x) maximum (S) Θ(1) extract_max(s) O(lg n) Implementazione: con heap. A.A. 24/25 Heap, heapsort e code a priorità 4
A.A. 24/25 Heap, heapsort e code a priorità 5 Esempio 2 15 1 12 11 5 4 9 8 5 7-1
Implementazione Struttura dati: vettore A[..length(A)-1] heap-size(a): numero di elementi in heap A radice in A[] dato A[i]: figlio SX in A[2i+1] figlio DX in A[2i+2] A.A. 24/25 Heap, heapsort e code a priorità 6
Esempio 2 1 15 2 1 3 12 4 11 5 5 6 4 A i 9 8 6 7-1 7 8 9 1 11 12 2 15 1 12 11 5 4 9 8 6 7-1 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 length(a) heapsize(a) A.A. 24/25 Heap, heapsort e code a priorità 7
Dato n = heap-size(a)-1: i n se i n/2, il nodo i ha due figli se i = n/2, il nodo i ha uno (n pari) o due (n dispari) figli se i > n/2, il nodo i non ha alcun figlio. A.A. 24/25 Heap, heapsort e code a priorità 8
Procedura Insert Aggiunge una foglia all albero (cresce per livelli da SX a DX, rispettando la proprietà strutturale) Risale dalla foglia fino al più alla radice confrontando con la chiave da inserire e facendo eventualmente scendere la chiave del padre nel figlio Inserisce la chiave nel nodo corrente. Complessità: T(n) = O(lg n). A.A. 24/25 Heap, heapsort e code a priorità 9
A.A. 24/25 Heap, heapsort e code a priorità 1 Esempio Inserzione di 17 2 1 15 2 1 3 12 4 11 5 5 6 4 creo foglia 9 8 6 7-1 7 8 9 1 11 12 13
A.A. 24/25 Heap, heapsort e code a priorità 11 2 3 1 15 2 1 12 4 11 5 5 6 confronto 17 e 4 e faccio scendere 4 9 8 6 7-1 7 8 9 1 11 12 4 13
A.A. 24/25 Heap, heapsort e code a priorità 12 2 1 15 2 confronto 17 e 1 e faccio scendere 1 3 12 4 11 5 5 6 1 9 8 6 7-1 7 8 9 1 11 12 4 13
A.A. 24/25 Heap, heapsort e code a priorità 13 2 inserisco 17 1 15 2 17 3 12 4 11 5 5 6 1 9 8 6 7-1 7 8 9 1 11 12 4 13
A.A. 24/25 Heap, heapsort e code a priorità 14 Implementazione C #define PARENT(i) ((i-1) / 2) void Insert(int A[], int x, int *pheapsize) { int i; i = ++(*pheapsize); while (i>1 && A[PARENT(i)] < x) { A[i] = A[PARENT(i)]; i = (i-1)/2; } A[i] = x; return; }
Procedura Heapify Trasforma in heap i, Left(i), Right(i), dove Left(i) e Right(i) sono già heap assegna ad A[i] il max tra A[i], Left(i) e Right(i) se c è stato scambio A[i] Left(i), applica ricorsivamente heapify su sottoalbero con radice Left(i) analogamente per scambio A[i] Right(i). Complessità: T(n) = O(lg n). A.A. 24/25 Heap, heapsort e code a priorità 15
A.A. 24/25 Heap, heapsort e code a priorità 16 Esempio Left(i) i=1 16 1 4 Right(i) 2 1 Heapify(A, 1) 14 = max(4, 14, 7) A[i] A[Left(i)] 3 14 4 7 5 9 6 3 2 8 1 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 17 i=3 16 1 14 2 1 Heapify(A, 3) 8 = max(4, 2, 8) A[i] A[Right(i)] Heapify(A, 8) Left(i) 3 4 4 7 5 9 6 3 Right(i) 2 8 1 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 18 16 1 14 2 1 Heapify(A, 8) foglia terminazione. 3 8 4 7 5 9 6 3 i = 8 2 4 1 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 19 Implementazione C #define LEFT(i) ((i*2) + 1) #define RIGHT(i) ((i*2) + 2) void Swap( int v[], int n1, int n2) { int temp; temp = v[n1]; v[n1] = v[n2]; v[n2] = temp; return; }
void Heapify(int A[], int i, int heapsize) { int l, r, largest; l = LEFT(i); r = RIGHT(i); if (l< heapsize && A[l]>A[i]) largest=l; else largest = i; if (r<heapsize && A[r]>A[largest]) largest=r; if (largest!= i) { Swap(A,i,largest); Heapify(A,largest,heapsize); } return; } A.A. 24/25 Heap, heapsort e code a priorità 2
Procedura BuildHeap Trasforma un albero binario memorizzato in vettore A in un heap: le foglie sono heap applica Heapify a partire dal padre dell ultima coppia di foglie fino alla radice. Complessità: T(n)= O(n). A.A. 24/25 Heap, heapsort e code a priorità 21
A.A. 24/25 Heap, heapsort e code a priorità 22 Esempio 4 BuildHeap(A) 1 1 2 3 3 2 4 16 5 9 6 1 14 8 7 Heapify(A, 4) 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 23 4 Heapify(A, 3) 1 1 2 3 3 2 4 16 5 9 6 1 14 8 7 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 24 Heapify(A, 2) 4 1 1 2 3 3 14 4 16 5 9 6 1 2 8 7 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 25 Heapify(A, 1) 4 1 16 2 1 3 14 4 7 5 9 6 3 2 8 1 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 26 Heapify(A, ) 16 1 14 2 1 3 8 4 7 5 9 6 3 2 4 1 7 8 9
A.A. 24/25 Heap, heapsort e code a priorità 27 Implementazione C void BuildHeap (int A[], int heapsize) { int i; for (i=(heapsize)/2-1; i >= ; i--){ Heapify(A,i,heapsize); } return; }
Procedura HeapSort Trasforma il vettore in uno heap Scambia il primo e ultimo elemento Ripristina la proprietà di heap Riduci la dimensione dello heap di 1 Ripeti fino a esaurimento dello heap. Complessità: T(n)= (n lg n). A.A. 24/25 Heap, heapsort e code a priorità 28
A.A. 24/25 Heap, heapsort e code a priorità 29 Esempio A 5 3 2 6 4 1 9 7 Configurazione iniziale 5 1 3 2 2 3 6 4 4 5 1 6 9 7 7
Applico Build_heap A 9 7 5 6 4 1 2 3 9 heapsize 1 7 2 5 3 6 4 4 5 1 6 2 7 3 A.A. 24/25 Heap, heapsort e code a priorità 3
A.A. 24/25 Heap, heapsort e code a priorità 31 A[] A[heapsize-1] heapsize-- A 3 7 5 6 4 1 2 9 3 heapsize 1 7 2 5 3 6 4 4 5 1 6 2 7 9
A.A. 24/25 Heap, heapsort e code a priorità 32 Heapify(A, ) A 7 6 5 3 4 1 2 9 7 heapsize 1 6 2 5 3 3 4 4 5 1 6 2 7 9
A.A. 24/25 Heap, heapsort e code a priorità 33 A[] A[heapsize-1] heapsize-- A 2 6 5 3 4 1 7 9 2 heapsize 1 6 2 5 3 3 4 4 5 1 6 7 7 9
A.A. 24/25 Heap, heapsort e code a priorità 34 Heapify(A, ) A 6 4 5 3 2 1 7 9 6 heapsize 1 4 2 5 3 3 4 2 5 1 6 7 7 98
Implementazione C void HeapSort(int A[], int heapsize) { int i; BuildHeap(A, heapsize); for (i=heapsize-1; i > ; i--) { Swap (A,,i); heapsize--; Heapify(A,,heapsize); } return; } A.A. 24/25 Heap, heapsort e code a priorità 35