Indirizzamento aperto
Un modo alternativo per risolvere le collisioni consiste nel memorizzare gli elementi con lo stesso hash nella tabella insieme agli altri, per poi cercarli attraverso l'ispezione di T[h(k)]
:
- Se la cella equivale a
k
la ricerca ha successo - Se equivale a
NIL
la ricerca termina con insuccesso - Se è diversa da
k
si trova il prossimo indice dall'ordine di ispezione, cioè il numero di ispezioni fatte
Si vuole quindi che la funzione hash rappresenti la posizione di in T
dopo ispezioni fallite:
con la condizione che per ogni la funzione assuma tutti i valori, così che ogni cella possa essere usata.
Implementazione
In queste versioni delle operazioni, per semplicità, gli elementi di T
sono solamente le chiavi stesse.
-
Inserimento
insert(T, k) i = j = 0 found = false while not found and i < m j = h(k, i) if T[j] == NIL or T[j] == DELETED T[j] = k found = true else i++ if found return j return NIL
-
Ricerca
search(T, k) i = j = 0 found = false do j = h(k, i) if T[j] == k found = true else i++ while not found and i < m and T[j] != NIL if found return j return NIL
-
Cancellazione
delete(T, k) T[search(T, k)] = DELETED
Il motivo per cui si usa
DELETED
invece cheNIL
è che quest'ultimo serve ad indicare la fine della catena di ricerca, e quindi porterebbe alla perdita dei valori sulle successive.Lo svantaggio di questo metodo è che il tempo di ricerca non dipende più da .
Metodi di ispezione
Come per il concatenamento, una funzione ideale rispetterebbe le proprietà dell'hashing uniforme così che, dato un , ogni è distribuito uniformemente sulle celle.
Dato che è difficile rispettarle, vengono adottate delle approssimazioni.
Ispezione lineare
dove è detta funzione hash ausiliaria.
Questo metodo è semplice, ma genera la stessa sequenza di ispezioni per le diverse con lo stesso .
Ispezione quadratica
dove è l'hash ausiliaria e sono costanti, con buoni valori e .
Anche in questo caso genera la stessa sequenza di ispezioni per diverse con uguali.
Doppio hashing
dove sono hash ausiliarie, di cui marca la cella di partenza mentre definisce lo step delle ispezioni.
Questo metodo genera sequenze diverse di ispezione, dato che dipendono da .
Per generare sequenze su tutti i valori della tabella, dev'essere relativamente primo con :
- Si usa pari e si definisce come sempre dispari, e.g.
- Si usa primo e minore di , e.g. , per
Tempo di ricerca
Al contrario del concatenamento, l'indice di prestazione perchè .
Se esiste almeno una cella vuota su cui la ricerca senza successo si può fermare, quindi:
- perchè la prima ispezione è sempre effettuata
- ovvero la probabilità che la cella su sia occupata
- perchè anche la cella su sia occupata
- perchè anche la cella su sia occupata
Di conseguenza il valore atteso di , ovvero il numero medio di ispezioni, è al massimo1: e lo stesso vale per l'inserimento, dato che cerca una cella vuota.
Nella ricerca con successo invece, il numero medio di ispezioni è .
CLRS, Introduction to Algorithms (4th ed.), pp. 298-299