Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Esempio:
Hash table 1
ad un NIL (elemento nullo).
Le operazioni in una tavola a indirizzamento diretto sono semplicissime!
Sembra una struttura molto efficiente, ma dal punto di vista dello spazio può
non risultare efficiente!
Infatti la quantità di memoria occupata dalla struttura dati dipende dai contesti in
cui viene utilizzata, se la tabella è molto grande rispetto alla quantità di dati
memorizzati realmente, la struttura non sarà efficiente.
Hash table 2
Ossia circa lo 0.4%
💡 In questi due ultimi casi , la struttura dati non è ragionevole come scelta, è
troppo costosa dal punto di vista dello spazio per implementarla!
Tavole hash
Quindi, l’indirizzamento diretto non è realizzabile se l’universo delle chiavi è troppo
grande
in ogni caso non è efficiente dal punto di vista della memoria utilizzata, può
capitare che troppa memoria sia usata per i puntatori nil.
Hash table 3
Non c’è più una corrispondenza diretta tra la posizione della tabella T e una
chiave di U , ma la posizione della chiave k è determinata usando una funzione:
Quindi nel caso delle tavole hash l’indirizzamento non è più diretto.
Hash table 4
💡 Nell’esempio precedente, le coppie (0, 5), (1, 6), (2, 7), (3, 8) sono in
collisione! infatti il resto della divisone per 5 è uguale per i due elementi
della coppia!
= k2 ⟹ h(k1 )
k1 = h(k2 )
Esempio:
Ogni volta che un elemento va in collisione, si inserisce nella lista puntata dall’hash
dell’elemento, ma l’inserimento viene sempre effettuato in testa! In questo modo non
devo scorrere tutta la lista e ho O(1)
Hash table 5
Operazioni nelle tavole hash con concatenamento:
Inserimento:
Ricerca:
Cancellazione:
Hash table 6
La ricerca di un elemento di chiave k richiede del tempo proporzionale alla
lunghezza della lista ∣T (h(k))∣
Il costo della ricerca dipende quindi dal numero di elementi e dalle caratteristiche
della funzione hash.
Mentre per quanto riguarda la cancellazione, essa richiede O(1) perchè assumiamo
di aver già individuato l’elemento.
In realtà non possiamo dire nulla senza sapere come è fatta la funzione hash.
Hash table 7
Il resto di una divisione per 10 corrisponde sempre all’ultima cifra della chiave.
Ognuno di questi numeri appare 10 volte come ultima cifra, quindi in questo caso la
funzione è uniforme!
In questo caso invece:
La funzione di hash in questo caso calcola la somma delle cifre della chiave
h(k) = 0 per k = 0
h(k) = 1 per k = 1, k = 10
h(k) = 2 per k = 2, k = 11, k = 20
Quindi la funzione non è uniforme semplice! Ci sono infatti delle posizioni della
tabella T con più elementi rispetto ad altre!
Hash table 8
chiamiamo ni il numero di elementi nella lista T [i] con i = 0, 1, .., m − 1
Il numero medio di elementi in una lista è
💡 Però possiamo immaginare che m sia scelto in modo che α sia quasi
costante
per trovare xi dobbiamo esaminare xi stesso e tutti gli elementi che sono stati
inseriti dopo xi e hanno una chiave con stesso valore di hash di xi !
Hash table 9
Quanti elementi tali ci sono?
💡 1
La sommatoria è moltiplicata per N per far si che ciascun elemento a
caso sia equiprobabile nella somma totale!
Hash table 10
1
La prima sommatoria vale quindi N ∗N =1
1 N N
La seconda vale N ∗N∗ m = M
Mentre la terza , essendo una serie aritmetica diventa
In definitiva otteniamo:
α α
1+ −
2 2N
Il tempo di calcolo può essere scritto come
α α
θ(1) + θ(1 + 2
− 2N
) = θ(1 + α)
Quindi esattamente come nel caso in cui l’elemento non è presente, il tempo di
calcolo della ricerca nel caso migliore è proporzionale al valore α
Hash table 11
Finora abbiamo interpretato le chiavi sempre come numeri naturali ed effettivamente
ogni chiave è una sequenza di bit!
E nella funzione hash si cerca di far si che ogni bit della chiave entri “in gioco”
h(k) = k mod m
è molto veloce, ma bisogna fare attenzione a m!
Esempio:
Hash table 12
Infatti, se si usa m= 2p , entrano in gioco solo le due ultime lettere della parola,
quindi si può scegliere m in questo modo soltanto se si ha la certezza che gli ultimi
bit hanno una distribuzione uniforme , per le parole italiane non va certamente bene!
Invece un numero primo non vicino ad una potenza di 2 è spesso una buona scelta (
m = 1583)
h(k) = [m(Ak mod 1)]
Avendo 4 parole piuttosto simili tra loro abbiamo 4 valori differenti di hash!
Indirizzamento aperto
Rispetto a prima, con l’indirizzamento aperto tutti gli elementi sono memorizzati nella
tavola T
In generale, l’elemento con chiave k viene inserito nella posizione h(k) se essa è
libera
Se invece la posizione h(k) non è libera, allora si cerca una posizione libera in base
ad uno schema di ispezione, che esamina altre posizioni fino a quando non si trova
una cella libera.
Hash table 13
Lo schema di ispezione più semplice è la cosiddetta ispezione lineare: a partire
dalla posizione h(k) l’elemento con chiave k viene inserito nella prima cella
libera!
Esempio
💡 Ad esempio, la chiave 2 va in
collisione con la chiave 12,
quindi il valore 2 viene
inserito tramite l’ispezione
lineare, e viene scelta la
posizione 3 visto che è libera!
Anche 22 va in collisione
siccome la posizione 2 è
occupata, e siccome anche la
3 è occupata la chiave 22
viene inserita in posizione 4.
Si osserva che con questa tecnica anche chiavi con hash diversi possono andare in
collisione, non è detto che una chiave si trovi nella posizione indicata dalla tabella
hash
Hash table 14
In generale, un elemento con chiave k viene inserito:
e cosi via…
L’ispezione è lineare se
Hash table 15
Ricerca in tabella hash con indirizzamento aperto
💡 Per questo motivo, dobbiamo assumere che non ci siano buchi nella
tabella e che non sia possibile la cancellazione di un elemento!
Hash table 16
💡 Nella pratica, l’indirizzamento aperto si usa quando non c’è necessità di
cancellare.
In questo caso, due chiavi con stesso valore di h1 non avranno in generale stesso
valore di h(k, i)!
Consideriamo, dal punto di vista della ricerca, il caso in cui l’elemento sia assente ,
che corrisponde al caso peggiore!
Denotiamo quindi con X il numero di celle esaminate durante una ricerca senza
successo
Assumendo che la chiave assente sia scelta a caso, è ovvio che X sia casuale
(variabile aleatoria), e ovviamente vale almeno 1 , quindi P (X ≥ 1) = 1.
Hash table 17
Qual’è la probabilità di esaminare almeno due celle? questo accade quando la
prima cella non è un nil, ma questo è N/m , infatti nella tabella sono occupate N
celle su m totali.
N
quindi P (X ≥ 2) = m
E la probabilità di esaminare almeno tre celle?
N N −1
P (X ≥ 3) = m
∗ m−1
In generale, la probabilità di esaminare almeno i celle è :
N N −1 N −i+2
P (X ≥ i) = ∗ ... ∗
m m−1 m−i+2
Siccome a noi interessa porre un limite superiore e ciascun elemento del prodotto è
minore di α, possiamo dire che
P (X ≥ i) ≤ ai−1
Ora, ci interessa il valor medio della variabile aleatoria X che indico con E[X]
Hash table 18