Hashing / Hash tabeller
-- Kapitel 20
Hash?

Varför en annan datastruktur?

Konstant tid för både insert- och findoperationer
Hash?
Insert
Find
”Daniel”
=18
Hashfunktioner!


Hash functioner använder associerade “key”
( som kan vara data i sig ) för att få fram
datan.
Hash funktionerna är olika för olika sorts
data.
Integers
 Images
 Strings
Etc…

Hashing integers?






Tänk 16bit int => 0 – 65 535
Skapa int[] vec = new int[65536];
Add i => vec[i]++;
Sök value j => Is vec[j] > 0?
Ta bort value k => vec[k]--;
Men för en ... Java int : 32bit

4 billion items => impractical!
Exempel av hash funktion
”Daniel”
D a n i e l
68 + 97 + 110 +105+ 101 +108 = 589
Men...

Hur unik är den?



hashfunc(”Daniel”) → 589
hashfunc(”leinaD”) → 589
Bättre lösning men….!


hashfunc(”TestValue”) → 129310392
Wrapp värdet till ett visst intervall

Vilken? Arraystorleken…
En bättre hash funktion





Ett bättre sätt att beräkna hash värdet
Om vi har en text sträng av längd n+1
och alla tecken har index An, An-1,...,A0
gör s = AnXn + An-1Xn-1 +...+ A0X0 =
= ((An)X + An-1)X +...+ A0
Använd hashValue = s % array.length
Och då......

For example: ”Danne”
(((’D’)128 + ’a’)128 + ’n’)128 + ’n’)128 + ’e’ =
(((68)128 + 97)128 + 110)128 + 110)128 + 101 =
18 458 851 173
hashValue = 18 458 851 173 % array.length
om length = 7919 (prim nummer) =>
hashValue = 18 458 851 173 % 7919
= 2690
Hur löser man kollision?


Oavsätt hur unika keys en hashfunktionen tar fram, kollision alltid
inträffas.
Terminology

Load factor

# used positions
LF 
# total avaliable positions
Lösningar




Linear probing ( undersökning ??)
Quadratic probing
Double hashing
Separate chaining
Linear probing

Sök fram till näst lediga platsen.
hashfunc( )
10
18
X=18
X+1,
X+2,
X+3,
X+4,
X+5,
...
Linear probing

Fenomen kallat: Primary clusters
Linear probing

Bygger upp kluster

Påverkar exekveringstiden för insert () och
find()!
Quadratic probing



Försök undvika“primary clusters “
Snabare en linjär
Kvadratisk inkrementation av
undersökning avståndet
X=18
X+12,
X+22,
X+32,
X+42,
X+52,
...
Quadratic probing
32 = 9
1
2
1
4

Garantera att hitta fria platser om de finns
Double hashing

Använder en till hash funktion för att
hitta fri plats.
X = hash(obj);
X2 = hash2(obj);
X=18, X2=7
X+1*X2, X+2*X2, X+3*X2, X+4*X2, ...
X=18, X2=7
18+1*7, 18+2*7, 17+3*7, 18+4*7, ...
Double hash probing
Hash2() = 3
3*3
1*3== 6
2*3=
39

Andra hash-funktionene Får inte
returnera 0!
Separate chaining



Varje hash position har en länkad lista.
Påverkar inte andra värde, probing
görs bara i listan.
Varje element I tabellen är en länkad
lista.
Separate chaining
Insert
H
H
H
H
H
H
H
H
H
Jämförelse

Linear probing



Quadratic probing



Kräver Load factor < 0.5 annars rehashing ??
Kräver prim tal för array storleken
Separate chaining




Enkel
Kan resultera i linjär söktid
LF < 1
Ingen dubblering, länkade listor är dinamiska !
Kan leda till linjär sökning men I verklighetet ganska kort
Double hash probing

Eliminerar kluster
Implementation Quadratic prob.
...
Object[] list = new Object[size]; // Prime length
...
int hash(Object o) {
int start= Math.abs(o.hashCode() % list.length);
int quadNbr = 0;
int index = start;
while(list[index] != null) {
index = start + Math.pow(++quadNbr, 2);
}
return pos;
}