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;
}