Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Tabelle
Operazioni:
insert(elem e, chiave k)
aggiunge ad S una nuova coppia (e, k)
delete(elem e, chiave k)
cancella da S la coppia con chaive k
search(chiave k)
se la chiave k è presente in s restituisce l’elemento
e ad esso associato altrimenti restituisce null
Operazioni su tabelle
Ricerca su tabelle
2 Tabelle Hash
Parte I
Universo
0
9 6
4 7 2
1
3
K 2
chiavi effettive 3 5
5
8
8
Direct-Address-Search(T , k) Direct-Address-Insert(T , x)
return T [k] T [key [x]] x
Direct-Address-Delete(T , x)
T [key [x]] nil
Inconvenienti
Inconvenienti
Universo
0
9 6
4 7 2
1
3
K 2
chiavi effettive 3 5
5
8
8
= spazio inutilizzato
Fattore di carico
Parte II
Tabelle Hash
Tabelle Hash
h : U 7! [0, 1, . . . m 1]
Tabelle Hash
Contro:
perdiamo la corrispondenza tra chiavi e posizioni in tabella
le tabelle hash possono so↵rire del fenomeno delle collisioni
Collisioni
Due chiavi k1 e k2 collidono quando corrispondono alla stessa
posizione della tabella, ossia quando h(k1 ) = h(k2 )
k1 6= k2 =) h(k1 ) 6= h(k2 )
Deve essere |U| m
Sia P(k) la probabilità che sia estratta una chiave k tale che
h(k) = j, allora
X 1
P(k) = per j = 0, . . . , m 1
m
k:h(k)=j
h(k) = k mod m
Semplice e veloce, ma occorre evitare certi valori di m; m non
dovrebbe essere una potenza di 2
k1 k4
k5 k2 k7
k3
k8 k6
Chained-Hash-Search(T , k)
ricerca un elemento con chiave k nella lista T [h(k)]
Chained-Hash-Insert(T , x)
inserisci x in testa alla lista T [h(key [x])]
Chained-Hash-Delete(T , x)
cancella x dalla lista T [h(key [x])]
Chained-Hash-Search(T , k)
il tempo di esecuzione è, nel caso peggiore, proporzionale
alla lunghezza della lista
Chained-Hash-Insert(T , x)
il tempo di esecuzione nel caso peggiore è O(1)
Chained-Hash-Delete(T , x)
se si usano liste bidirezionali, può richiedere un tempo O(1)
con liste semplici, richiede lo stesso tempo della ricerca
Ipotesi:
Proof:
Occorre O(1) tempo per il calcolo della funzione h(k); inoltre
si deve scorrere completamente la lista T [h(k)].
n n n
1X i 1 1 X X i 1
(1 + )= 1+ =
n m n m
i=1 i=1 i=1
n n 1
1 1 X 1 1 X
n+ (i 1) = n + i) =
n m n m
i=1 i=0
1 1 n(n 1) n 1
n+ =1+ =
n m 2 2m
↵ 1
1+ = ⇥(1 + ↵)
2 2m
Indirizzamento Aperto
Indirizzamento Aperto
Prevede che si usi solo lo spazio della tabella, senza uso di
zone di trabocco, allocando gli elementi che determinano
collisioni in posizioni diverse da quella che loro competerebbe
Indirizzamento Aperto
h : U ⇥ {0, 1, . . . , m 1} ! {0, 1, . . . , m 1}
Operazione di Inserimento
Hash-Insert(T , k)
i 0
repeat
j h(k, i)
if T [j] = nil or T [j] = deleted
then T [j] = k return j
else i i +1
until i = m
error “overflow sulla tabella hash”
Operazione di Ricerca
Hash-Search(T , k)
i 0
repeat
j h(k, i)
if T [j] = k return j
i i +1
until T [j] = nil or i = m
return nil
Operazione di Cancellazione
Il problema della cancellazione di un elemento in una tabella hash
ad indirizzamento aperto è appena un pò più complesso
Cosı̀ facendo i tempi di ricerca non dipendo più solo dal fattore di
carico ↵; l’uso di liste di collisione è più comune se si ammettono
cancellazioni frequenti
Di Berardini, Merelli Algoritmi e Strutture Dati
Liste di collisione
Liste di collisione: analisi
Tabelle Hash
Indirizzamento aperto
Indirizzamento aperto: analisi
Fact
1
X 1
X
i · Pr {X = i} = Pr {X i}
i=0 i=1
Se denotiamo con
allora 1 1
X X
i · pi = qi
i=0 i=1
1
X 1
X 1
X 1
X
i 1
1+ i · pi = 1 + qi 1 + ↵ = ↵i =
i=0 i=1 i=1 i=0
1 ↵
Inserimento
Inserimento – dimostrazione
1 1 1 m
= = =
(1 ↵i ) (1 i/m) (m i/m) (m i)
Eseguendo la media su tutte le n chiavi nella tabella hash si ottiene
un numero medio di accessi
n 1 n 1 n 1
1 X m m X 1 1 X 1
= =
n i=0 (m i) n i=0 (m i) ↵ i=0 (m i)
n 1
X m
X
1 1
= (ponendo k = m i)
(m i) k
i=0 k=m n+1
m
X Z m n
1 1 m 1
dx = ln m ln(m n) = ln( ) = ln( )
k m x m n 1 ↵
k=m n+1
Parte III
Scansione Lineare
Scansione Lineare
Scansione Lineare
4
h0 (k) #acc
5
0 6
6 1 5
7 2 4
8 3 3
9 4 2
posizioni occupate 5–9 1
9
1 X 1
#acc[h0 (k) = i] = · 25 = 2.5
10 10
i=0
5
h0 (k) #acc
6 pari 2
7 dispari 1
8
9
1
((2 · 5) + (1 · 5)) = 1.5
10
posizioni occupate
Inoltre ...
Scansione Quadratica
Scansione Quadratica
Un esempio:
dove, c1 = c2 = 1
h(k, 0) = h0 (k),
h(k, 1) = h0 (k) + 1 + 1 = h0 (k) + 2,
h(k, 2) = h0 (k) + 2 + 4 = h0 (k) + 6,
h(k, 3) = h0 (k) + 3 + 9 = h0 (k) + 12,
h(k, 4) = h0 (k) + 4 + 16 = h0 (k) + 20
Scansione Quadratica
Hashing Doppio
Hashing Doppio
0
k = 14
1 79
2 h1(k) = k mod 13 = 1
3 h2(k) = 1 + (k mod 11) = 4
4 69 h(k, i) = (1 + i • 4) mod 13
5 98
6 h(k,0) = 1 mod 13 = 1
7 h(k,1) = (1 + 1·4) mod 13 = 5
8
9
10
11 50
12
Hashing Doppio
0
k = 14
1 79
2 h1(k) = k mod 13 = 1
3 h2(k) = 1 + (k mod 11) = 4
4 69 h(k, i) = (1 + i • 4) mod 13
5 98
6
7 h(k,0) = 1 mod 13 = 1
8 h(k,1) = (1 + 1·4) mod 13 = 5
h(k,2) = (1 + 2·4) mod 13 = 9
9 14
10
11 50
12
Hashing Doppio
La prima posizione esaminata è T [h1 (k)] mod m; ogni posizione
esaminata successivamente è distanziata dalla precedente di una
quantità h2 (k) mod m
Hashing Doppio
0
K = 14
1 79
2 h1(k) = k mod 13 = 1
3 h2(k) = 1 + (k mod 10) = 5
4 69
5 98 h2(k) non è primo con m
6 15
7 h(k,0) = (1 + 0·5) mod 10 = 1
8 h(k,1) = (1 + 1·5) mod 10 = 6
9 h(k,2) = (1 + 2·5) mod 10 = 1
h(k,3) = (1 + 3·5) mod 10 = 6
h(k,4) = (1 + 4·5) mod 10 = 1
....
Hashing Doppio