Sei sulla pagina 1di 122

Code a priorità e heap

Paolo Camurati
Dip. Automatica e Informatica
Politecnico di Torino
ADT 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

 Implementazione: mediante vettore.

A.A. 2020/21 14 Code a priorità e heap 2


Esempio
a 20

z 15 ba 10

d 12 m 11 g 5 e 4

x 9 y 8 pp 5 w 7 k 2 b 0

A.A. 2020/21 14 Code a priorità e heap 3


Item

item name value


 Quasi ADT Item
 Dati:
chiave
 Nome (stringa), valore (intero)
 Chiave = valore
 Tipologia 3

A.A. 2020/21 14 Code a priorità e heap 4


 Operazioni:
 HEAPify(Heap h, int i);
 HEAPbuild(Heap h);
 HEAPsort(Heap h);
 funzioni di servizio
 HEAPinit(int maxN);
 HEAPfree(Heap h);
 HEAPfill(Heap h, Item val);
 HEAPdisplay(Heap h);

A.A. 2020/21 14 Code a priorità e heap 5


ADT di I classe Heap
Heap.h
typedef struct heap *Heap;

Heap HEAPinit(int maxN);


Void HEAPfree(Heap h);
void HEAPfill(Heap h, Item val);
void HEAPsort(Heap h);
void HEAPdisplay(Heap h);

A.A. 2020/21 14 Code a priorità e heap 6


Implementazione
 Struttura dati: vettore di Item h->A[0..maxN-1]
 h->heapsize(A): numero di elementi in heap h->A
 radice in h->A[0]
 dato h->A[i]:
 il figlio SX è h->A[LEFT(i)] dove LEFT(i)= 2i+1

 il figlio DX è h->A[RIGHT(i)] dove

RIGHT(i) = 2i+2
 il padre è h->A[PARENT(i)] dove

PARENT(i)=(i-1)/2
A.A. 2020/21 14 Code a priorità e heap 7
0 a20

Esempio 1 2 ba10
z15

3 d12 4 m11 5 g5 6 e4

maxN = 15 x9 y 8 pp 5 w 7 k2 b0
7 8 9 10 11 12

a z ba d m g e x y pp w k b
h->A
20 15 10 12 11 5 4 9 8 5 7 2 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

h->heapsize 13

A.A. 2020/21 14 Code a priorità e heap 8


Heap.c
#include <stdio.h>
#include <stdlib.h>
#include "Item.h"
#include "Heap.h"

struct heap { Item *A; int heapsize; };

int LEFT(int i) { return (i*2 + 1); }


int RIGHT(int i) { return (i*2 + 2); }
int PARENT(int i) { return ((i-1)/2); }

Heap HEAPinit(int maxN) {


Heap h;
h = malloc(sizeof(*h));
h->A = malloc(maxN*sizeof(Item));
h->heapsize = 0;
return h;
}
A.A. 2020/21 14 Code a priorità e heap 9
usata per inserire valori,
non necessariamente
il risultato sarà uno heap
void HEAPfree(Heap h) {
free(h->A);
free(h);
}

void HEAPfill(Heap h, Item item) {


int i;
i = h->heapsize++;
h->A[i] = item;
return;
}

void HEAPdisplay(Heap h) {
int i;
for (i = 0; i < h->heapsize; i++)
ITEMstore(h->A[i]);
}

A.A. 2020/21 14 Code a priorità e heap 10


Funzione 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], A[LEFT(i)]
e A[RIGHT(i)]
 se c’è stato scambio A[i]  A[LEFT(i)],
applica ricorsivamente HEAPify su
sottoalbero con radice LEFT(i)
 analogamente per scambio A[i] 
A[RIGHT(i)].
 Complessità: T(n) = O(lg n).

A.A. 2020/21 14 Code a priorità e heap 11


Esempio
HEAPify(h->A, 1)
i=1 0 16 14 = max(4, 14, 7)
h->A[i]  h->A[LEFT(i)]
LEFT(i) 1 4 RIGHT(i) 2 10

3 14 4 7 5 9 6 3

2 8 1 Sono visualizzate solo le


7 8 9 chiavi intere, non gli item

A.A. 2020/21 14 Code a priorità e heap 12


HEAPify(h->A, 3)
8 = max(4, 2, 8)
0 16
h->A[i]  h->A[RIGHT(i)]
HEAPify(h->A, 8)
i=3 1 14 2 10

3 4 4 7 5 9 6 3
LEFT(i) RIGHT(i)

2 8 1
7 8 9

A.A. 2020/21 14 Code a priorità e heap 13


HEAPify(h->A, 8)
0 16 foglia
terminazione.
1 14 2 10

3 8 4 7 5 9 6 3
i=8

2 4 1
7 8 9

A.A. 2020/21 14 Code a priorità e heap 14


void HEAPify(Heap h, int i) {
int l, r, largest;
l = LEFT(i);
r = RIGHT(i);
if ((l<h->heapsize) &&
KEYcmp(KEYget(h->A[l]),KEYget(h->A[i]))==1)
largest = l;
else
largest = i;
if ((r<h->heapsize) &&
KEYcmp(KEYget(h->A[r]), KEYget(h->A[largest]))==1)
largest = r;
if (largest != i) {
Swap(h, i,largest);
HEAPify(h, largest);
}
}

A.A. 2020/21 14 Code a priorità e heap 15


Funzione HEAPbuild

Trasforma un albero binario memorizzato in


vettore A in uno heap:
 le foglie sono heap

 applica HEAPify a partire dal padre


dell’ultima foglia o coppia di foglie fino alla
radice.
void HEAPbuild (Heap h) {
int i;
for (i=(h->heapsize)/2-1; i >= 0; i--)
HEAPify(h, i);
}

A.A. 2020/21 14 Code a priorità e heap 16


Esempio

Sono visualizzate solo le HEAPbuild(h->A)


chiavi intere, non gli item
0 4

1 1 2 3

3 2 4 16 5 9 6 10

14 8 7
HEAPify(h->A, 4)
7 8 9

A.A. 2020/21 14 Code a priorità e heap 17


0 4

HEAPify(h->A, 3) 1 1
2 3

3 2 4 16 5 9 6 10

14 8 7
7 8 9

A.A. 2020/21 14 Code a priorità e heap 18


HEAPify(h->A, 2)
0 4

1 1 2 3

3 14 4 16 5 9 6 10

2 8 7
7 8 9

A.A. 2020/21 14 Code a priorità e heap 19


HEAPify(h->A, 1)
0 4

1 1 2 10

3 14 4 16 5 9 6 3

2 8 7
7 8 9

A.A. 2020/21 14 Code a priorità e heap 20


HEAPify(h->A, 0)

0 4

1 16 2 10

3 14 4 7 5 9 6 3

2 8 1
7 8 9

A.A. 2020/21 14 Code a priorità e heap 21


0 16

1 14 2 10

3 8 4 7 5 9 6 3

2 4 1
7 8 9

A.A. 2020/21 14 Code a priorità e heap 22


Analisi di complessità:
 intuitiva ed imprecisa: n passi ciascuno di
costo logn, quindi T(n) = O(n lg n)
2 sottoalberi
 precisa: T(n) = O(n). Heapify
Risoluzione per sviluppo (unfolding):
T(n) = 2T(n/2) + log2(n)
T(n/2) = 2T(n/4) + log2(n/2)
T(n/4) = 2T(n/8) + log2(n/4)

A.A. 2020/21 14 Code a priorità e heap 23


σ𝑘𝑖=0 𝑖𝑥𝑖 = x (1-(k+1)xk+kxk+1)/(1-x)2

Sostituendo in T(n):
𝑙𝑜𝑔 𝑛
T(n) = σ𝑖=02 2ilog2(n/2i)
𝑙𝑜𝑔2𝑛 i 𝑙𝑜𝑔2𝑛 i
= log2n 𝑖=0 2 − 𝑖=0 i2
σ σ
= log2n(2n-1) -2(1-(log2n+1)n+2nlog2n)
= 2n –log2n -2
= O(n)

A.A. 2020/21 14 Code a priorità e heap 24


Funzione HEAPsort
 Trasforma il vettore in uno heap mediante
HEAPbuild
 Scambia il primo e ultimo elemento

 Riduci la dimensione dello heap di 1

 Ripristina la proprietà di heap

 Ripeti fino a esaurimento dello heap.

Caratteristiche:
 complessità: T(n)= O(n lg n).

 in loco

 non stabile

A.A. 2020/21 14 Code a priorità e heap 25


Sono visualizzate solo le
chiavi intere, non gli item
Esempio
Configurazione iniziale

h->A 5 3 2 6 4 1 9 7

0 5

1 3 2 2

3 6 4 4 5 1 6 9

7 7

A.A. 2020/21 14 Code a priorità e heap 26


Applico HEAPbuild

h->A 9 7 5 6 4 1 2 3
h->heapsize = 8
0 9

1 7 2 5

3 6 4 4 5 1 6 2

7 3

A.A. 2020/21 14 Code a priorità e heap 27


h->A[0]  h->A[h->heapsize-1]
h->heapsize--
h->A 3 7 5 6 4 1 2 9
h->heapsize = 7
0 3

1 7 2 5

3 6 4 4 5 1 6 2

7 9

A.A. 2020/21 14 Code a priorità e heap 28


HEAPify(h->A, 0)
h->A 7 6 5 3 4 1 2 9
h->heapsize = 7
0 7

1 6 2 5

3 3 4 4 5 1 6 2

7 9

A.A. 2020/21 14 Code a priorità e heap 29


h->A[0]  h->A[h->heapsize-1]
h->heapsize--
h->A 2 6 5 3 4 1 7 9
H->heapsize = 6
0 2

1 6 2 5

3 3 4 4 5 1 6 7

7 9

A.A. 2020/21 14 Code a priorità e heap 30


HEAPify(h->A, 0)
h->A 6 4 5 3 2 1 7 9
h->heapsize = 6
0 6

1 4 2 5

3 3 4 2 5 1 6 7

7 9

A.A. 2020/21 14 Code a priorità e heap 31


void HEAPsort(Heap h) {
int i, j;
HEAPbuild(h);
j = h->heapsize;
for (i = h->heapsize-1; i > 0; i--) {
Swap (h,0,i);
h->heapsize--;
HEAPify(h,0);
}
h->heapsize = j;
}

A.A. 2020/21 14 Code a priorità e heap 32


Coda a priorità
Definizione:
 struttura dati PQ per mantenere un set di
elementi di tipo Item, ciascuno dei quali include
un campo priorità
 operazioni principali: inserzione, estrazione del
massimo, lettura del massimo, cambio di
priorità.

A.A. 2020/21 14 Code a priorità e heap 33


ADT di I classe Coda a Priorità
PQ.h
typedef struct pqueue *PQ;

PQ PQinit(int maxN);
void PQfree(PQ pq);
int PQempty(PQ pq);
void PQinsert(PQ pq, Item val);
Item PQextractMax(PQ pq);
Item PQshowMax(PQ pq);
void PQdisplay(PQ pq);
int PQsize(PQ pq);
void PQchange(PQ pq, Item val);

discussione a parte

A.A. 2020/21 14 Code a priorità e heap 34


Implementazione della struttura dati:
 vettore/lista non ordinato

 vettore/lista ordinato

non considerati qui,
cfr Tipi di Dato Astratto
 heap di dati/indici.

A.A. 2020/21 14 Code a priorità e heap 35


Complessità:
PQinsert PQshowMax PQextractMax
Vettore non 1 N N
ordinato
Lista non 1 N N
ordinata max in coda
Vettore N 1 1
ordinato
max in testa
Lista N 1 1
ordinata
Heap di logN 1 logN
item/indici

A.A. 2020/21 14 Code a priorità e heap 36


Cosa contiene l’ADT Coda a priorità?
I soluzione: la coda a priorità contiene dati (lo
heap che realizza la coda a priorità contiene i
dati), l’ADT è una struct con:
1. la coda a priorità: vettore (heap) pq->A di
dati di tipo Item (quasi ADT, tipologia 3)
2. heapsize: intero. chiave2 = nome
item
name prio

chiave1 = priorità
A.A. 2020/21 14 Code a priorità e heap 37
Utente ADT I cat. coda a priorità di dati

PQinsert(pq, item) a q zz qa cd s w c
item pq->A
81 70 20 48 5 9 19 15
PQshowMax(pq)
item 0 1 2 3 4 5 6 7 8 9

PQextractMax(pq) pq->heapsize 8
item

A.A. 2020/21 14 Code a priorità e heap 38


a q zz qa cd s w c
pq->A
81 70 20 48 5 9 19 15
0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 a 81

1 q 70 2 zz 20

3 qa48 4 cd 5 5 s 9 6 w19

7 c 15

A.A. 2020/21 14 Code a priorità e heap 39


ADT di I cat. Coda a priorità di dati
PQ.c
#include <stdlib.h>
#include "Item.h"
#include "PQ.h"

struct pqueue { Item *A; int heapsize; };

static int LEFT(int i) { return (i*2 + 1); }


static int RIGHT(int i) { return (i*2 + 2); }
static int PARENT(int i) { return ((i-1)/2); }

PQ PQinit(int maxN){
PQ pq = malloc(sizeof(*pq));
pq->A = (Item *)malloc(maxN*sizeof(Item));
pq->heapsize = 0;
return pq;
}
A.A. 2020/21 14 Code a priorità e heap 40
void PQfree(PQ pq){
free(pq->array);
free(pq);
}

int PQempty(PQ pq) { return pq->heapsize == 0; }

int PQsize(PQ pq) { return pq->heapsize; }

Item PQshowMax(PQ pq) { return pq->A[0]; }

void PQdisplay(PQ pq) {


int i;
for (i = 0; i < pq->heapsize; i++)
ITEMstore(pq->A[i]);
}

A.A. 2020/21 14 Code a priorità e heap 41


Funzione PQinsert
 Aggiunge una foglia all’albero (cresce per livelli
da SX a DX, rispettando la proprietà strutturale)
 Risale dal nodo corrente (inizialmente la foglia
appena creata) fino al più alla radice. Confronta
la chiave del dato contenuto nel padre con la
chiave del dato da inserire, facendo scendere il
dato del padre nel figlio se la chiave da inserire è
maggiore, altrimenti inserisce il dato nel nodo
corrente.
Complessità: T(n) = O(lg n).

A.A. 2020/21 14 Code a priorità e heap 42


void PQinsert (PQ pq, Item val) {
int i;
i = pq->heapsize++;
while((i>=1) &&
(KEYcmp(KEYget(pq->array[PARENT(i)]),KEYget(val))==-1)){
pq->A[i] = pq->A[PARENT(i)];
i = (i-1)/2;
}
pq->A[i] = val;
return;
}

A.A. 2020/21 14 Code a priorità e heap 43


Esempio a q zz qa cd s w c
pq->A
81 70 20 48 5 9 19 15
Inserzione di r 75
0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 a81

1 q70 2 zz20

3 qa48 4 cd 5 5 s9 6 w19

7 c15

A.A. 2020/21 14 Code a priorità e heap 44


pq->A a q zz qa cd s w c
81 70 20 48 5 9 19 15

0 1 2 3 4 5 6 7 8 9
pq->heapsize 9

0 a81

1 q70 2 zz20

3 qa48 4 cd 5 5 s9 6 w19

i=9
7 c15 8 creo foglia
A.A. 2020/21 14 Code a priorità e heap 45
pq->A a q zz qa cd s w c qa
81 70 20 48 5 9 19 15 48

0 1 2 3 4 5 6 7 8 9
pq->heapsize 9

0 a81

1 q70 2 zz20

3 qa48 4 cd 5 5 s9 6 w19

7 c15 8 qa48 i >1 && 75 > 48 faccio


scendere qa 48 e i = 3
A.A. 2020/21 14 Code a priorità e heap 46
pq->A a q zz q cd s w c qa
81 70 20 70 5 9 19 15 48
i >1 && 75 > 70 0 1 2 3 4 5 6 7 8 9
faccio scendere
q 70 e i = 1 pq->heapsize 9

0 a81

1 q70 2 zz20

3 q 70 4 cd 5 5 s9 6 w19

7 c15 8 qa48

A.A. 2020/21 14 Code a priorità e heap 47


pq->A a r zz q cd s w c qa
81 75 20 70 5 9 19 15 48

0 1 2 3 4 5 6 7 8 9
i >1 && 75 < 81 pq->heapsize 9
inserisco r 75
0 a81

1 r 75 2 zz20

3 q 70 4 cd 5 5 s9 6 w19

7 c15 8 qa48

A.A. 2020/21 14 Code a priorità e heap 48


Funzione PQextractMax

Modifica lo heap, estraendone il valore massimo,


che è contenuto nella radice:
 scambia la radice con l'ultima delle foglie
(quella più a destra nell'ultimo livello)
 riduce di 1 della dimensione dello heap
 ripristina le proprietà dello heap mediante
applicazione di HEAPify.
Complessità: T(n) = O(lg n).

A.A. 2020/21 14 Code a priorità e heap 49


Item PQextractMax(PQ pq) {
Item val;
Swap (pq, 0,pq->heapsize-1);
val = pq->A[pq->heapsize-1];
pq->heapsize--;
HEAPify(pq, 0);
return val;
}

A.A. 2020/21 14 Code a priorità e heap 50


Esempio a r zz q cd s w c qa
pq->A
81 75 20 70 5 9 19 15 48

0 1 2 3 4 5 6 7 8 9
pq->heapsize 9

0 a81

1 r 75 2 zz20

3 q70 4 cd 5 5 s9 6 w19

7 c15 8 qa48

A.A. 2020/21 14 Code a priorità e heap 51


pq->A qa r zz q cd s w c a
48 75 20 70 5 9 19 15 81

0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 qa48

1 r 75 2 zz20

3 q70 4 cd 5 5 s9 6 w19

pq->A[0]  pq->A[pq->heapsize-1]
7 c15 8 a81 pq->heapsize--
A.A. 2020/21 14 Code a priorità e heap 52
pq->A r q zz qa cd s w c a
75 70 20 48 5 9 19 15 81
HEAPify(pq->A, 0)
0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 r 75

1 q70 2 zz20

3 qa48 4 cd 5 5 s9 6 w19

7 c15 8 a81

A.A. 2020/21 14 Code a priorità e heap 53


Funzione PQchange
 Modifica la priorità di un elemento, la cui
posizione (indice nello heap) viene calcolata con
una scansione di costo lineare
 O risale dalla posizione data fino al più alla radice
confrontando la chiave del padre con la chiave
modificata, facendo scendere la chiave del padre
nel figlio se la chiave modificata è maggiore,
altrimenti la inserisce nel nodo corrente
 O applica HEAPify a partire dalla posizione data.

Complessità: T(n) = O(n) + O(lg n) = O(n).


A.A. 2020/21 14 Code a priorità e heap 54
Esempio a q zz qa cd s w c
pq->A
81 70 20 48 5 9 19 15

0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 a81
Cambio la priorità di w da 19
a 90. L’elemento si trova
1 q70 2 zz20 all’indice 6.

3 qa48 4 cd 5 5 s9 6 w19

7 c15

A.A. 2020/21 14 Code a priorità e heap 55


pq->A a q zz qa cd s zz c
81 70 20 48 5 9 20 15

0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 a81
20 < 90,
1 q70 zz 20 scende
2 zz20

3 qa48 4 cd 5 5 s9 6 zz20

7 c15

A.A. 2020/21 14 Code a priorità e heap 56


pq->A a q a qa cd s zz c
81 70 81 48 5 9 20 15
81 < 90,
0 1 2 3 4 5 6 7 8 9
a 81 scende
pq->heapsize 8

0 a81

1 q70 2 a 81

3 qa48 4 cd 5 5 s9 6 zz20

7 c15

A.A. 2020/21 14 Code a priorità e heap 57


pq->A w q a qa cd s zz c
90 70 81 48 5 9 20 15
radice:
0 1 2 3 4 5 6 7 8 9
inserisco w 90
pq->heapsize 8

0 w90

1 q70 2 a 81

3 qa48 4 cd 5 5 s9 6 zz20

7 c15

A.A. 2020/21 14 Code a priorità e heap 58


Esempio pq->A w q a qa cd s zz c
90 70 81 48 5 9 20 15

0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

0 w90
Cambio la priorità di q da 70
a 3. L’elemento si trova
1 q70 2 a 81 all’indice 1.

3 qa48 4 cd 5 5 s9 6 zz20

7 c15

A.A. 2020/21 14 Code a priorità e heap 59


pq->A w q a qa cd s zz c
90 3 81 48 5 9 20 15

0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

cambio 70 in 3 0 w90

1 q3 2 a 81

3 qa48 4 cd 5 5 s9 6 zz20

7 c15

A.A. 2020/21 14 Code a priorità e heap 60


pq->A w qa a c cd s zz q
90 48 81 15 5 9 20 3

0 1 2 3 4 5 6 7 8 9
pq->heapsize 8

applico HEAPify 0 w90

1 qa48 2 a 81

3 c15 4 cd 5 5 s9 6 zz20

7 q3

A.A. 2020/21 14 Code a priorità e heap 61


void PQchange (PQ pq, Item val) {
int i, found = 0, pos;
for (i = 0; i < pq->heapsize && found == 0; i++)
if (NAMEcmp(NAMEget(&(pq->array[i])), NAMEget(&val))==0) {
found = 1;
pos = i;
}

if (found==1) {
while(pos>=1 &&
PRIOget(pq->array[PARENT(pos)])<PRIOget(val)){
pq->array[pos] = pq->array[PARENT(pos)];
pos = (pos-1)/2;
}
pq->array[pos] = val;
Heapify(pq, pos);
}
else
printf("key not found!\n");
return;
}
A.A. 2020/21 14 Code a priorità e heap 62
Cosa contiene l’ADT Coda a priorità?

II soluzione: lo heap che realizza la coda a priorità


contiene gli indici dei dati. L’ADT è una struct che
contiene:
1. il vettore pq->vett con i dati di tipo Item
(quasi ADT, tipologia 3) e la sua dimensione
pq->vettsize
item name prio

chiave per la tabella di simboli priorità usata per prendere


decisioni nella coda a priorità
A.A. 2020/21 14 Code a priorità e heap 63
2. la tabella di simboli (tabella di hash) pq->hash
con dati di tipo Item e loro indici in pq->vett
3. uno stack di interi pq->stack per gestire
eventuali estrazioni del massimo e reinserimenti
usando posizioni riutilizzabili in pq->vett
4. la coda a priorità: vettore (heap) pq->heap degli
indici dei dati in pq->vett e la sua dimensione
pq->heapsize
5. il vettore pq->qp per memorizzare a quale indice
nello heap della coda a priorità si trova un certo
dato.
A.A. 2020/21 14 Code a priorità e heap 64
Lo stack pq->stack memorizza la posizione
in pq->vett degli item estratti. Sono le
posizioni disponibili in pq->vett in caso di
inserzione di un nuovo item.

Il vettore pq->qp serve per implementare


PQchange, identificando la posizione
dell’elemento nello heap senza bisgno di
una scansione lineare.

A.A. 2020/21 14 Code a priorità e heap 65


 il client fornisce e riceve i dati
 il vettore pq->vett memorizza i dati e gestisce
la corrispondenza indice/dato
 la tabella di hash pq->hash gestisce la
corrispondenza dato/indice con costo O(1) nel
caso medio
 la coda a priorità pq->heap memorizza gli
indici dei dati
 le decisioni sono prese in base ai confronti
sulle priorità dei dati

A.A. 2020/21 14 Code a priorità e heap 66


Quasi ADT Item
Item.h
#define MAXC 10

typedef struct {
char name[MAXC];
int prio;
} Item; funzioni su elementi
di tipo Item
typedef char *Name;

Item ITEMscan();
void ITEMstore(Item val); funzioni su:
Item ITEMsetNull();
• nome
Name NAMEget(Item *pval); • priorità
int NAMEcmp(Name n1, Name n2);
int PRIOget(Item val);

A.A. 2020/21 14 Code a priorità e heap 67


Item.c
...
Item ITEMscan() {
Item val;
printf("name and priority: ");
scanf("%s %d", val.name, &val.prio);
return val;
}
void ITEMstore(Item val) {
printf("name= %s priority= %d", val.name, val.prio);
}
Item ITEMsetNull(){
Item val = {"", -1};
return val;
}
Name NAMEget(Item *pval) { return pval->name;}
int NAMEcmp(Name n1, Name n2) {return strcmp(n1, n2);}
int PRIOget(Item val) {return val.prio;}
A.A. 2020/21 14 Code a priorità e heap 68
inserisce elemento e
suo indice in st->a
ST.h
typedef struct symboltable *ST;

ST STinit(int maxN);
void STfree(ST st);
int STinsert(ST st, Item val, int index);
int STsearch(ST st, Item val, int *index);
void STchangePrio(ST st, Item val, int i);

cerca e ritorna
un elemento e il
cambia la priorità di un
suo indice in
elemento in posizione i
st->a
A.A. 2020/21 14 Code a priorità e heap 69
tabella di hash con open addressing, linear
probing e cancellazione logica

ST.c
...
struct symboltable { Item *a; int *ind; int M;};

ST STinit(int maxN, float alpha) {


int i; ST st = malloc(sizeof(*st));
st->N = 0; st->M = STsizeSet(maxN, alpha);
if (st->M == -1) st = NULL;
else {
st->a = malloc(st->M * sizeof(Item) );
st->ind = malloc(st->M * sizeof(int) );
for (i = 0; i < st->M; i++) {
st->a[i] = ITEMsetNull(); st->ind[i] = -1;
}
}
return st;
}
void STfree(ST st) {free(st->a); free(st->ind); free(st);}
A.A. 2020/21 14 Code a priorità e heap 70
static int CheckFull(ST st, int i) {
if (st->ind[i] != -1)
return 1;
return 0;
}
static int CheckDeleted(ST st, int i){
if (st->ind[i] != -1 && st->ind[i] != -2)
return 1;
return 0;
}
void STinsert(ST st, Item item, int index) {
int i = hash(NAMEget(&item), st->M);
while (CheckDeleted(st, i))
i = (i+1)%st->M;
st->a[i] = item;
st->ind[i] = index;
st->N++;
}
A.A. 2020/21 14 Code a priorità e heap 71
indice dell’elemento
in pq->hash

int STsearch(ST st, Item val, int *index) {


int i = hash(NAMEget(&val), st->M);
while (CheckFull(st, i))
if (NAMEcmp(
NAMEget(&val), NAMEget(&st->a[i])) == 0) {
*index = i;
return st->ind[i];
}
else indice dell’elemento
i = (i+1)%st->M; in pq->vett
*index = -1;
return -1;
}
void STchangePrio(ST st, Item val, int i){ st->a[i] = val;}

void STdelete(ST st, int i){ st->ind[i]=-2; }

A.A. 2020/21 14 Code a priorità e heap 72


Stack.h
typedef struct stack *S;

S STACKinit(int maxN);
void STACKfree(S s);
void STACKpush(S s, int index);
int STACKpop(S s);

A.A. 2020/21 14 Code a priorità e heap 73


stack con lista

Stack.c
...
typedef struct STACKnode* link;
struct STACKnode { int index; link next; };

struct stack {link top; int N; };

link NEW(int ind, link next) {


link x = (link)malloc(sizeof *x);
x->index = ind; x->next = next;
return x;
}

S STACKinit(int maxN) {
S s = malloc(sizeof *s);
s->top = NULL; s->N = 0;
return s;
}
A.A. 2020/21 14 Code a priorità e heap 74
void STACKfree(S s) {
link t, u;
for (t = s->top; t != NULL; t = u){
u = t->next; free(t);
}
free(s->top);
free(s);
}
void STACKpush(S s, int ind) {
s->top = NEW(ind, s->top); (s->N)++;
}
int STACKpop(S s) {
int ind = s->top->index;
link t = s->top->next;
free(s->top); s->top = t; (s->N)--;
return ind;
}
A.A. 2020/21 14 Code a priorità e heap 75
PQ.h
typedef struct pqueue *PQ;

PQ PQinit(int maxN);
void PQfree(PQ pq);
int PQempty(PQ pq);
int PQsize(PQ pq);
void PQinsert(PQ pq, Item val);
Item PQshowMax(PQ pq);
Item PQextractMax(PQ pq);
void PQdisplay(PQ pq);
void PQchange(PQ pq, Item val);

A.A. 2020/21 14 Code a priorità e heap 76


PQ.c
...
struct pqueue {int *heap; int heapsize; Item *vett;
int vettsize; ST hash; int *qp; S stack; };

PQ PQinit(int maxN) {
int i; float alpha=0.5;
PQ pq = malloc(sizeof(*pq));
pq->heap = malloc(maxN*sizeof(int));
pq->vett = malloc(maxN*sizeof(Item));
pq->vettsize = 0;
pq->hash = STinit(maxN, alpha);
pq->qp = malloc(maxN*sizeof(int));
for (i=0; i < maxN; i++){
pq->heap[i] = -1; pq->qp[i] = -1;
pq->vett[i] = ITEMsetNull();
}
pq->heapsize = 0;
pq->stack = STACKinit(maxN);
return pq;
}
A.A. 2020/21 14 Code a priorità e heap 77
void PQfree(PQ pq) {
STACKfree(pq->stack);
free(pq->qp);
STfree(pq->hash);
free(pq->vett);
free(pq->heap);
free(pq);
}

int PQempty(PQ pq){


return pq->heapsize == 0;
}

int PQsize(PQ pq) {


return pq->heapsize;
}
A.A. 2020/21 14 Code a priorità e heap 78
Funzione PQinsert

 Inserisce in pq->vett inserire, eventualmente


riusando celle svuotate da estrazioni. I loro indici
sono in pq->stack
 Inserisce l’elemento in pq->vett e in pq->hash

 risale dal nodo corrente (inizialmente la foglia


appena creata) fino al più alla radice. Poiché lo
heap contiene indici e non dati, si usa pq->vett
per ottenere il dato contenuto nel padre, la cui
priorità è confrontata con la priorità del dato da
inserire. Si mantiene aggiornato pq->qp.
A.A. 2020/21 14 Code a priorità e heap 79
decido a che indice leggo in pq->vett l’item del
inserire in pq->vett padre del nodo corrente e
confronto la sua priorità con
quella dell’elemento da inserire
void PQinsert (PQ pq, Item item){
int i, j;
if (STACKempty(pq->stack)) j = pq->vettsize++;
else j=STACKpop(pq->stack);
i=pq->heapsize++;
pq->vett[j] = item;
STinsert(pq->hash, item, j);
while((i>=1) &&
(PRIOget(pq->vett[pq->heap[PARENT(i)]])<PRIOget(item))){
pq->heap[i] = pq->heap[PARENT(i)];
pq->qp[pq->heap[i]] = j;
i = (i-1)/2;
}
pq->heap[i] = j;
pq->qp[j] = i;
}
aggiorno pq->qp
A.A. 2020/21 14 Code a priorità e heap 80
Esempio
Si inseriscano in sequenza in una coda a priorità
inizialmente vuota i seguenti dati (maxN=6):

ZZ/20, A/81, DA/15, CD/5, Q/70

Si supponga che la tabella di hash sia:


A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

A.A. 2020/21 14 Code a priorità e heap 81


inserzione di ZZ, 20
pq
ZZ inserisco in pq->vett
pq->vett 20 e pq->hash
0 1 2 3 4
ZZ
pq->hash
20
0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap pq->heapsize 0
0 1 2 3 4
pq->qp pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 82
0 0

inserzione di ZZ, 20
pq
ZZ creo nuova foglia e
pq->vett 20 aggiorno heapsize
0 1 2 3 4
ZZ
pq->hash
20
0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap pq->heapsize 1
0 1 2 3 4
pq->qp pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 83
ZZ
0 0 0 20

inserzione di ZZ, 20
pq
ZZ sono nella radice:
pq->vett 20 pq->heap[0]=0
0 1 2 3 4 pq->qp[0]=0
ZZ
pq->hash
20
0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 0 pq->heapsize 1
0 1 2 3 4
pq->qp 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 84
ZZ
0 0 0 20

inserzione di A, 81
pq
ZZ A inserisco in pq->vett
pq->vett 20 81 e pq->hash
0 1 2 3 4
A ZZ
pq->hash
81 20
1 0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 0 pq->heapsize 1
0 1 2 3 4
pq->qp 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 85
ZZ
0 0 0 20

inserzione di A, 81 1 1

pq
ZZ A creo nuova foglia e
pq->vett 20 81 aggiorno heapsize
0 1 2 3 4
A ZZ
pq->hash
81 20
1 0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 0 pq->heapsize 2
0 1 2 3 4
pq->qp 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 86
ZZ
0 0 0 20
ZZ
inserzione di A, 81 1 0 1 20

pq
ZZ A i >=1 && 81>20, ZZ (0)
pq->vett 20 81 scende, pq->heap[1]=0
0 1 2 3 4 e pq->qp[0]=1
A ZZ
pq->hash
81 20
1 0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 0 0 pq->heapsize 2
0 1 2 3 4
pq->qp 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 87
A
0 1 0 81
ZZ
inserzione di A, 81 1 0 1 20

pq
ZZ A sono nella radice:
pq->vett 20 81 pq->heap[0]=1
0 1 2 3 4 pq->qp[1]=0
A ZZ
pq->hash
81 20
1 0
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 pq->heapsize 2
0 1 2 3 4
pq->qp 1 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 88
A
0 1 0 81
ZZ
inserzione di DA, 15 1 0 1 20

pq
ZZ A DA inserisco in pq->vett
pq->vett 20 81 15 e pq->hash
0 1 2 3 4
A ZZ DA
pq->hash 15
81 20
1 0 2
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 pq->heapsize 2
0 1 2 3 4
pq->qp 1 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 89
A
0 1 0 81
ZZ
inserzione di DA, 15 1 0 2 1 20 2

pq
ZZ A DA creo nuova foglia e
pq->vett 20 81 15 aggiorno heapsize
0 1 2 3 4
A ZZ DA
pq->hash 15
81 20
1 0 2
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 pq->heapsize 3
0 1 2 3 4
pq->qp 1 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 90
A
0 1 0 81
ZZ
inserzione di DA, 15 1 0 2 2 1 20 2
DA
15

pq
ZZ A DA i >=1 && 15<81:
pq->vett 20 81 15 pq->heap[2]=2
0 1 2 3 4 pq->qp[2]=2
A ZZ DA
pq->hash 15
81 20
1 0 2
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 pq->heapsize 3
0 1 2 3 4
pq->qp 1 0 2 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 91
A
0 1 0 81
ZZ
inserzione di CD, 5 0 2 2 1 20 2
DA
15

pq
ZZ A DA CD inserisco in pq->vett
pq->vett 20 81 15 5 e pq->hash
0 1 2 3 4
A ZZ DA CD
pq->hash 15
81 20 5
1 0 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 pq->heapsize 3
0 1 2 3 4
pq->qp 1 0 2 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 92
A
0 1 0 81
ZZ
inserzione di CD, 5 1 0 2 2 1 20 2
DA
15

3 3 pq
ZZ A DA CD creo nuova foglia e
pq->vett 20 81 15 5 aggiorno heapsize
0 1 2 3 4
A ZZ DA CD
pq->hash 15
81 20 5
1 0 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 pq->heapsize 4
0 1 2 3 4
pq->qp 1 0 2 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 93
A
0 1 0 81
ZZ
inserzione di CD, 5 1 0 2 2 1 20 2
DA
15
CD

3 3 3 5 pq
ZZ A DA CD i >=1 && 5<20:
pq->vett 20 81 15 5 pq->heap[3]=3
0 1 2 3 4 pq->qp[3]=3
A ZZ DA CD
pq->hash 15
81 20 5
1 0 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 3 pq->heapsize 4
0 1 2 3 4
pq->qp 1 0 2 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 94
A
0 1 0 81
ZZ
inserzione di Q, 70 1 0 2 2 1 20 2
DA
15
CD

3 3 3 5 pq
ZZ A DA CD Q inserisco in pq->vett
pq->vett 20 81 15 5 70 e pq->hash
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 3 pq->heapsize 4
0 1 2 3 4
pq->qp 1 0 2 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 95
A
0 1 0 81
ZZ
inserzione di Q, 70 1 0 2 2 1 20 2
DA
15
CD

3 3 4 3 5 4 pq
ZZ A DA CD Q creo nuova foglia e
pq->vett 20 81 15 5 70 aggiorno heapsize
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 3 pq->heapsize 5
0 1 2 3 4
pq->qp 1 0 2 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 96
A
0 1 0 81
ZZ
inserzione di Q, 70 1 0 2 2 1 20 2
DA
15
CD ZZ

3 3 4 0 3 5 4 20 pq
ZZ A DA CD Q i >=1 && 70>20, ZZ (0)
pq->vett 20 81 15 5 70 scende, pq->heap[4]=0
0 1 2 3 4 e pq->qp[0]=4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 0 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 97
A
0 1 0 81
Q
inserzione di Q, 70 1 4 2 2 1 70 2
DA
15
CD ZZ

3 3 4 0 3 5 4 20 pq
ZZ A DA CD Q i >=1 && 70<81:
pq->vett 20 81 15 5 70 pq->heap[1]=4
0 1 2 3 4 pq->qp[4]=1
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 98
Funzione PQextractMax
Modifica pq->heap, estraendone il valore
massimo, che è contenuto nella radice:
 scambia la radice con l'ultima delle foglie
(quella più a destra nell'ultimo livello)
 riduce di 1 della dimensione dello heap
 ripristina le proprietà dello heap mediante
applicazione di HEAPify
 l’accesso al dato avviene attraverso pq->vett
 HEAPify e Swap aggiornano anche pq->qp.
A.A. 2020/21 14 Code a priorità e heap 99
Modifica pq->vett e pq->hash:
 inserisce l’indice dell’elemento estratto in
pq->stack per futuro eventuale riuso
 cancella logicamente l’elemento estratto da
pq->hash

A.A. 2020/21 14 Code a priorità e heap 100


void Swap(PQ pq, int n1, int n2){
int temp;
temp = pq->heap[n1];
pq->heap[n1] = pq->heap[n2];
pq->heap[n2] = temp;
n1 = pq->heap[n1];
n2 = pq->heap[n2];
temp = pq->qp[n1];
pq->qp[n1] = pq->qp[n2];
pq->qp[n2] = temp;
}

A.A. 2020/21 14 Code a priorità e heap 101


static void Heapify(PQ pq, int i) {
int l, r, largest;
l = LEFT(i);
r = RIGHT(i);
if (l < pq->heapsize &&
(PRIOget(pq->vett[pq->heap[l]]) >
PRIOget(pq->vett[pq->heap[i]])))
largest = l;
else
largest = i;
if (r < pq->heapsize &&
(PRIOget(pq->vett[pq->heap[r]]) >
PRIOget(pq->vett[pq->heap[largest]])) )
largest = r;
if (largest != i) {
Swap(pq, i,largest);
Heapify(pq, largest);
}
}

A.A. 2020/21 14 Code a priorità e heap 102


Item PQextractMax(PQ pq) {
Item item;
int j=0;

Swap (pq, 0, pq->heapsize-1);


item = pq->vett[pq->heap[pq->heapsize-1]];
STACKpush(pq->stack,pq->heap[pq->heapsize-1]);
pq->heapsize--;
Heapify(pq, 0);
STdelete(pq->hash,j);
pq->qp[pq->heap[pq->heapsize]]=-1;
pq->heap[pq->heapsize]=-1;
return item;
}

A.A. 2020/21 14 Code a priorità e heap 103


A
0 1 0 81
Q DA

Esempio 1 4 2 2 1
CD
70

ZZ
2 15

3 3 4 0 3 5 4 20 pq
ZZ A DA CD Q
pq->vett 20 81 15 5 70
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 104
ZZ
0 0 0 20
Q DA
1 4 2 2 1 70 2 15
CD A

3 3 4 1 3 5 4 81 pq
ZZ A DA CD Q scambio pq->heap[0] e
pq->vett 20 81 15 5 70 pq->heap[pq->heapsize-1]
0 1 2 3 4 push dell’indice 1 su pq->stack
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 0 4 2 3 1 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack 1
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 105
ZZ
0 0 0 20
Q DA
1 4 2 2 1 70 2 15
CD

3 3 3 5 pq
ZZ A DA CD Q decremento heapsize
pq->vett 20 81 15 5 70 cancello da pq->hash
0 1 2 3 4 aggiorno pq->qp
A ZZ Q DA CD
pq->hash
81 20 70 15 5
-2 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 0 4 2 3 pq->heapsize 4
0 1 2 3 4
pq->qp 0 -1 2 3 1 pq->stack 1
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 106
Q
0 4 0 70
ZZ DA
1 0 2 2 1 20 2 15
CD

3 3 3 5 pq
ZZ A DA CD Q applico Heapify(pq->heap[0]),
pq->vett 20 81 15 5 70 aggiorno pq->qp
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
-2 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 4 0 2 3 pq->heapsize 4
0 1 2 3 4
pq->qp 1 -1 2 3 0 pq->stack 1
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 107
Q
0 4 0 70
ZZ
inserzione di XX, 1 DA
1 0 2 2 1 20 2 15
CD

3 3 3 5 pq
ZZ A DA CD Q pop 1 da pq->stack, inserisco
pq->vett 20 81 15 5 70 XX, 1 in pq->vett[1]
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
-2 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 4 0 2 3 pq->heapsize 4
0 1 2 3 4
pq->qp 1 -1 2 3 0 pq->stack 1
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 108
Q
0 4 0 70
ZZ DA
1 1 2 2 1 20 2 15
CD

3 3 4 3 5 4 pq
ZZ XX DA CD Q inserisco XX, 1 in pq->hash
pq->vett 20 1 15 5 70 creo foglia, aggiorno heapsize
0 1 2 3 4
A ZZ Q DA XX CD
pq->hash
81 20 70 15 1 5
-2 0 4 2 6 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 4 0 2 3 pq->heapsize 5
0 1 2 3 4
pq->qp 1 -1 2 3 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 109
Q
0 4 0 70
ZZ DA
1 0 2 2 1 20 2 15
CD XX

3 3 4
1 3 5 4 1 pq
ZZ XX DA CD Q i >=1 && 1<20:
pq->vett 20 1 15 5 70 pq->heap[4]=1
0 1 2 3 4 pq->qp[1]=4
A ZZ Q DA XX CD
pq->hash
81 20 70 15 1 5
-2 0 4 2 6 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 4 0 2 3 1 pq->heapsize 5
0 1 2 3 4
pq->qp 1 4 2 3 0 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 110
Funzione PQchange
 La tabella di hash pq->hash ritorna con costo
unitario l’indice dell’elemento
 Il vettore pq->qp, dato l’indice dell’elemento,
ritorna con costo unitario la posizione
dell’elemento nello heap
 Si risale dalla posizione data fino al più alla radice
confrontando la chiave del padre con la chiave
modificata, facendo scendere la chiave del padre
nel figlio se la chiave modificata è maggiore,
altrimenti la inserisce nel nodo corrente
 Si applica HEAPify a partire dalla posizione data.
A.A. 2020/21 14 Code a priorità e heap 111
indice dell’elemento indice dell’elemento
in pq->vett in pq->hash
void PQchange (PQ pq, Item item) {
int i, pos, temp, j;
i = STsearch(pq->hash, item, &j);
if (i == -1) {
printf("Item not found!\n");
return;
}
if (i == -2) {
printf("Item deleted!\n");
return;
}
STchangePrio(pq->hash, item, j);

modifica dell’elemento in pq->hash

A.A. 2020/21 14 Code a priorità e heap 112


posizione dell’elemento con indice i in pq->heap

pos = pq->qp[i];
temp = pq->heap[pos];
pq->vett[i] = item;
posizionamento corretto in risalita

while ((pos>=1) &&


(PRIOget(pq->vett[pq->heap[PARENT(pos)]])
<
PRIOget(item))) {
pq->heap[pos] = pq->heap[PARENT(pos)];
pq->qp[pq->heap[pos]] = pos;
pos = (pos-1)/2;
} modifica dell’elemento in pq->heap
pq->heap[pos] = temp; aggiornamento di pq->qp
pq->qp[temp] = pos;

Heapify(pq, pos); posizionamento corretto in discesa


}
A.A. 2020/21 14 Code a priorità e heap 113
Esempio:
A
0 1 0 81
Q DA

CD da 5 a 90 1 4 2 2 1
CD
70

ZZ
2 15

3 3 4 0 3 5 4 20 pq
ZZ A DA CD Q
pq->vett 20 81 15 5 70
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 114
A
0 1 0 81
Q DA
1 4 2 2 1 70 2 15
CD ZZ

3 3 4 0 3 5 4 20 pq
ZZ A DA CD Q da pq->hash ricavo:
pq->vett 20 81 15 5 70 indice di CD in pq->vett: 3
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 115
A
1 0 81
Q DA
1 4 2 2 1 70 2 15
CD ZZ

3 3 4 0 3 5 4 20 pq
ZZ A DA CD Q da pq->qp ricavo:
pq->vett 20 81 15 5 70 indice di CD (3) in pq->heap: 3
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 5
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 116
A
1 0 81
Q DA
1 4 2 2 1 70 2 15
CD ZZ

3 3 4 0 3 90 4 20 pq
ZZ A DA CD Q aggiorno priorità in pq->vett
pq->vett 20 81 15 90 70 e pq->hash
0 1 2 3 4
A ZZ Q DA CD
pq->hash
81 20 70 15 90
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 3 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 1 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 117
A
1 0 81
Q DA
1 4 2 2 1 70 2 15
Q ZZ

3 4 4 0 3 70 4 20 pq
ZZ A DA CD Q i >=1 && 90>70, Q (4)
pq->vett 20 81 15 90 70 scende, pq->heap[3]=4
0 1 2 3 4 e pq->qp[4]=3
A ZZ Q DA CD
pq->hash
81 20 70 15 90
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 4 2 4 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 0 2 3 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 118
A
1 0 81
A DA
1 1 2 2 1 81 2 15
Q ZZ

3 4 4 0 3 70 4 20 pq
ZZ A DA CD Q i >=1 && 90>81, A (1)
pq->vett 20 81 15 90 70 scende, pq->heap[1]=1
0 1 2 3 4 e pq->qp[1]=1
A ZZ Q DA CD
pq->hash
81 20 70 15 90
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 1 1 2 4 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 1 2 3 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 119
CD
3 0 90
A DA
1 1 2 2 1 81 2 15
Q ZZ

3 4 4 0 3 70 4 20 pq
ZZ A DA CD Q sono nella radice
pq->vett 20 81 15 90 70 pq->heap[0]=3
0 1 2 3 4 e pq->qp[3]=0
A ZZ Q DA CD
pq->hash
81 20 70 15 90
1 0 4 2 3
0 1 2 3 4 5 6 7 8 9 10 11 12

pq->heap 3 1 2 4 0 pq->heapsize 5
0 1 2 3 4
pq->qp 4 1 2 0 3 pq->stack
0 1 2 3 4
A.A. 2020/21 14 Code a priorità e heap 120
Riferimenti
 Heap:
 Cormen 7.2, 7.3
 Sedgewick 9.2, 9.3
 Heapsort:
 Cormen 7.4
 Sedgewick 9.4
 Code a priorità:
 Cormen 7.5
 Sedgewick 9.1, 9.6

A.A. 2020/21 14 Code a priorità e heap 121


Esercizi di teoria
 7. Code a priorità e heap
• 7.1 Heap
• 7.2 Heap Sort
• 7.3 Code a priorità

A.A. 2020/21 14 Code a priorità e heap 122

Potrebbero piacerti anche