Algoritmi e Strutture Dati
Capitolo 7
Tavole hash
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Implementazioni Dizionario
Tempo richiesto dall’operazione più costosa:
- Liste e array
O(n)
- Alberi di ricerca non bilanciati
O(n)
- Alberi di ricerca bilanciati
O(log n)
- Tavole hash
O(1)
…ma a certe condizioni!
2
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Preambolo: tavole ad accesso diretto
Sono dizionari basati sulla proprietà di
accesso diretto alle celle di un array
Idea:
– Supponiamo che a ciascun elemento sia associata
una chiave intera nell’intervallo [0,m-1]
– Il dizionario viene memorizzato in un array v di
m celle
– L’elemento con chiave k è contenuto in v[k]
– Al più n≤m elementi nel dizionario
3
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Implementazione
4
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Fattore di carico
Misuriamo il grado di riempimento di una
tavola ad accesso diretto usando il fattore
di carico
n
=
m
Esempio: tavola con i nomi di 100 studenti
indicizzati da numeri di matricola a 6 cifre
n=100 m=106  = 0,0001 = 0,01%
Grande spreco di memoria!
5
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Pregi e difetti
Pregi:
– Tutte le operazioni richiedono tempo O(1)
Difetti:
– Le chiavi devono essere necessariamente interi
in [0, m-1] (non possiamo accogliere un
elemento con chiave  m)
– Lo spazio utilizzato è proporzionale alla chiave
più grande m, non al numero n di elementi:
può esserci grande spreco di memoria!
6
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Tavole hash
Per ovviare agli inconvenienti delle tavole
ad accesso diretto ne consideriamo
un’estensione: le tavole hash
Idea:
– Chiavi prese da un universo totalmente
ordinato U (possono non essere numeri)
– Funzione hash: h: U  [0, m-1]
(funzione che trasforma chiavi in indici)
– Elemento con chiave k in posizione v[h(k)]
7
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Collisioni
Le tavole hash possono soffrire del
fenomeno delle collisioni.
Si ha una collisione quando si deve inserire
nella tavola hash un elemento con chiave u, e
nella tavola esiste già un elemento con chiave
v tale che h(u)=h(v): il nuovo elemento
andrebbe a sovrascrivere il vecchio!
8
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Funzioni hash perfette
Un modo per evitare il fenomeno delle
collisioni è usare funzioni hash perfette.
Una funzione hash si dice perfetta se è
iniettiva, cioè per ogni u,v  U:
u  v  h(u)  h(v)
NOTA: Ovviamente, deve essere |U| ≤ m
9
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Implementazione
10
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio
Tavola hash con i nomi di 100 studenti
aventi come chiavi numeri di matricola
nell’insieme U=[234717, 235717]
Funzione hash perfetta: h(k) = k - 234717
n=100
m=1001
 = 0,1 = 10%
…ma il vincolo m ≥ |U| necessario per
avere una funzione hash perfetta è
raramente conveniente (o possibile)…
11
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Funzioni hash non perfette
Una funzione hash si dice non perfetta se
non è iniettiva, cioè esistono u,v  U per
cui:
u  v  h(u)  h(v)
Si potrebbero quindi avere collisioni,
ovverosia, può accadere che esistano 2 chiavi
u e v tali che uv ma h(u)=h(v).
12
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio
Tavola hash con elementi aventi come chiavi le
26 lettere dell’alfabeto inglese U={A,B,C,…,Z}
Funzione hash non perfetta:
h(k) = ascii(k) mod m con m<26
Ad esempio, per m=11:
h(‘C’) = 67 mod 11=1
h(‘N’)= 78 mod 11=1  h(‘C’) = h(‘N’)
 se volessimo inserire sia ‘C’ che ‘N’
nel dizionario avremmo una collisione!
13
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Ridurre al minimo le collisioni
Per ridurre la probabilità di collisioni, una
buona funzione hash dovrebbe essere in
grado di distribuire in modo quanto più
uniforme possibile le chiavi nello spazio
degli indici della tavola
Questo si ha ad esempio se la funzione hash
gode della proprietà di uniformità semplice
14
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Uniformità semplice
Sia P(k) la probabilità che la chiave k sia
presente nel dizionario e sia:
la probabilità che la cella i sia occupata.
Def: La funzione hash h gode dell’uniformità
semplice se, per ogni intero i in [0,m-1]:
15
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio
Se U è l’insieme dei numeri reali in [0,1) e
ogni chiave ha la stessa probabilità di essere
scelta, allora è semplice dimostrare che la
funzione hash:
soddisfa la proprietà di uniformità semplice
NOTA: Anche la funzione modulo soddisfa la proprietà di
uniformità semplice quando U coincide con l’insieme dei
numeri naturali e le chiavi sono equidistribuite
16
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Risoluzione delle collisioni
Nel caso in cui non si possano evitare le
collisioni, dobbiamo trovare un modo per
risolverle. Due metodi classici sono i seguenti:
1. Liste di collisione (n≥m,  ≥1). Gli elementi
sono contenuti in liste esterne alla tabella: v[i]
punta alla lista degli elementi tali che h(k)=i
2. Indirizzamento aperto (n ≤ m,  ≤ 1). Tutti
gli elementi sono contenuti nella tabella: se
una cella è occupata, se ne cerca un’altra libera
17
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Ipotesi di lavoro
• Da questo momento in poi, ai soli fini
esemplificativi, ammetteremo la possibilità
che le chiavi primarie non siano associate in
modo univoco agli elementi, e supporremo
che gli elementi contengono una chiave
secondaria di disambiguazione
18
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
1. Liste di collisione
Esempio di tabella
hash basata sulla
funzione hash
h(k) = ascii(k) mod 11
e su liste di
collisione,
contenente le
lettere della parola:
PRECIPITEVOLIS
SIMEVOLMENTE
19
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Implementazione
NOTA: Ho variato la specifica delle operazioni per adeguarmi
al fatto che le chiavi non sono univoche
20
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
2. Indirizzamento aperto
Supponiamo di voler inserire un elemento con
chiave k e la sua posizione “naturale” h(k) sia
già occupata.
L’indirizzamento aperto consiste nell’occupare
un’altra cella, anche se potrebbe spettare di
diritto a un’altra chiave.
Cerchiamo la cella vuota (se c’è) scandendo le
celle secondo una sequenza di indici:
c(k,0), c(k,1), c(k,2),…c(k,m-1)
21
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Metodi di scansione: scansione lineare
Scansione lineare:
c(k,i) = ( h(k) + i ) mod m
per 0 ≤ i < m
22
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio
Inserimenti in tavola
hash basata sulla
funzione hash
h(k)=ascii(k) mod 31
e su indirizzamento
aperto con scansione
lineare delle lettere
della parola:
PRECIPITEVOLIS
SIMEVOLMENTE
4,8 celle scandite in media per inserimento
23
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Il problema dell’agglomerazione primaria
• La scansione lineare provoca effetti di
agglomerazione primaria, cioè lunghi gruppi di
celle consecutive occupate che rallentano la
scansione: infatti, più cresce la dimensione di
un gruppo di celle contigue occupate, e più tale
insieme di celle tenderà a crescere!
24
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Metodi di scansione: scansione quadratica
Scansione quadratica: risolve il problema
dell’agglomerazione primaria
c(k,i) = ( h(k) + c1i +c2i2) mod m
per 0 ≤ i < m
Si può dimostrare che per c1=c2=0.5
e m potenza di 2 viene scandita tutta
la tavola
25
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Metodi di scansione: hashing doppio
• La scansione quadratica risolve il problema
dell’agglomerazione primaria, ma provoca
invece agglomerazione secondaria: coppie di
chiavi collidenti generano la stessa sequenza di
scansione: h(k1)=h(k2)  c(k1,i)=c(k2,i)
L’hashing doppio riduce il problema:
c(k,i) =  h1(k) + i·h2(k)  mod m
per 0 ≤ i < m, h1 e h2 funzioni hash
26
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Esempio
Inserimenti in tavola
hash basata sulla
funzione hash
h1(k)=ascii(k) mod 31
h2(k)=ascii(k) mod 30
e su indirizzamento
aperto con hashing
doppio delle lettere
della parola:
PRECIPITEVOLIS
SIMEVOLMENTE
3,1 celle scandite in media per inserimento
27
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Analisi del costo di scansione
• Nel caso peggiore, O(m)
• Nel caso medio, un’operazione di ricerca
di una chiave, assumendo che le chiavi
siano prese con probabilità uniforme da
U, costa:
dove =n/m (fattore di carico)
28
Copyright © 2004 - The McGraw - Hill Companies, srl
Algoritmi e strutture dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano
Riepilogo
• La proprietà di accesso diretto alle celle di un array
consente di realizzare dizionari con operazioni in tempo
O(1) indicizzando gli elementi usando le loro stesse chiavi
(purché siano intere)
• L’array può essere molto grande se lo spazio delle chiavi è
grande
• Per ridurre questo problema si possono usare funzioni hash
che trasformano chiavi (anche non numeriche) in indici
• Usando funzioni hash possono aversi collisioni
• Tecniche classiche per risolvere le collisioni sono liste di
collisione e indirizzamento aperto
29
Copyright © 2004 - The McGraw - Hill Companies, srl