35
1 Hashtabellen Datastructuren

1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

Embed Size (px)

Citation preview

Page 1: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

1

Hashtabellen

Datastructuren

Page 2: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

2

Dit onderwerp

• Direct-access-tabellen

• Hashtabellen– Oplossen van botsingen met “ketens” (chaining)– Analyse– Oplossen van botsingen door “open addressing”

• HashfunctiesHash: “mix”, “schud” …Hash: “mix”, “schud” …

Page 3: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

3

Datastructuren voor Dictionaries

• Operaties op een verzameling:– Zoek (Search)

– VoegToe (Insert)

– LaatWeg (Delete)

• Veel toepassingen

• Andere datastructuur: Zoekbomen– Bieden meer operaties (successor, minimum, etc.)

– Zijn in de praktijk wat langzamer als we alleen zoeken, toevoegen, en weglaten

– Komen later

Page 4: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

4

Direct-access tabellen

• Array met positie (slot) voor elke mogelijke key

• Grootte array dus even groot als aantal mogelijke keys

• Nadeel: veel geheugen als er veel verschillende keys zijn

• Soms nuttig: bij weinig keys– Bijv. Key is lengte persoon in

mm (< 3000 verschillende keys)

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

3 + extra info

6 + extra info

11 + extra info

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

Page 5: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

5

Hash-tabellen

• Als er veel keys zijn

– Is een direct-access-table te groot

– Maar kunnen we iets anders doen: hashtabel

• Neem een functie f, die iedere mogelijke key afbeeldt op een positie in de tabel (hashfunctie)

• Iets doen als er meer keys op dezelfde plek komen

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

3 + extra info

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

40 + extra info

28 + extra info

f(x) = x mod 17

Page 6: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

6

Hash-functies

• Stel iedere key komt uit een universum U (eindige of oneindige verzameling)

• We hebben een functie h: U {0, 1, …, m-1} – m is de grootte van

de tabel / het array

• Vaak gebruikte hashfuncties:

• U = N = {0, 1, 2, …}• h(k) = k mod m• Goede waardes voor m:

priemgetallen, niet in de buurt van 2-macht

• Slechte waardes voor m: machten van 2, machten van 10, …

Page 7: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

7

Oplossen van botsingen: “ketens”

• Botsingen (collisions): als we twee keys x en y willen hashen met h(x) == h(y)

• Oplossing 1: op elke positie van de hashtabel een pointer naar een gelinkte lijst (chaining)

• Oplossing 2: slim op een andere plek in de tabel zetten (open addressing) komt later

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

3

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

leeg

23 6

28 62

Page 8: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

8

Hashing met chaining

• Gelinkte lijst per positie in de tabel• NIL als lijst leeg• Chained-Hash-Insert(T,x)

– Voeg x toe aan kop van de lijst T[h(key(x))]• Chained-Hash-Search(T,x)

– Loop door de lijst T[h(key(x))] totdat je aan het eind van de lijst gekomen bent (false) of je een element met key x tegenkomt (gevonden, lever element op)

• Chained-Hash-Delete(T,x)– Loop door de lijst T[h(key(x))] totdat je aan het eind van de lijst gekomen

bent (false) of je een element met key x tegenkomt en delete dan dat element

• Tijd:– Insert O(1), – Search en Delete O(1+lengte T[h(key(x))])

Page 9: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

9

Analyse van zoeken en weglaten

• Tijd is lineair in lengte van de gelinkte lijst van de betreffende key

• Stel tabel heeft m posities• Stel we slaan n elementen op• Slechtste geval: alle elementen hashen naar zelfde positie:

(n) tijd• In het gemiddelde geval gaat het wel vaak goed, als we een

“goede” hashfunctie hebben• “Simple uniform hashing” aanname: elk element heeft

kans 1/m voor elk van de slots, onafhankelijk van de andere elementen– Is in feite een versimpeling van de werkelijkheid, maar helpt wel om

een redelijk inzicht te krijgen

Page 10: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

10

Uniforme verdeling

• Kansberekening: uniforme verdeling• Kansexperiment met aantal mogelijke

uitkomsten• Uniforme verdeling: elke uitkomst is even

waarschijnlijk– Eerlijke dobbelsteen: elke uitkomst heeft kans

1/6– Eerlijke munt: kans op kop = kans op munt = ½

Page 11: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

11

Verwachtingswaarde

• Stel, we herhalen een experiment k keer. Elk experiment kan “succesvol” of “onsuccesvol” zijn.

• Wat is het verwachtte aantal keren dat we succes hebben?

Page 12: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

12

Aanname: onafhankelijkheid

• Twee experimenten zijn onafhankelijk als

– Pr(x and y) = Pr(x) * Pr(y)• Intuïtie: uitkomst voor ene experiment beïnvloedt niet de

uitkomst voor het andere experiment• Als we een experiment herhalen, is de aanname dat de

opeenvolgende experimenten onafhankelijk zijn– In de praktijk een UITERST goede benadering van de

werkelijkheid– Slijtage van dobbelsteen zou dobbelsteenworpen afhankelijk

kunnen maken maar effect is zo klein dat het verwaarloosbaar is

Page 13: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

13

Aantal successen bij herhaald experiment

• E(aantal successen bij k keer een experiment met kans 1/q) = k/q

• E(aantal successen bij k keer een experiment met kans p) = kp

• E: verwachtingswaarde

Page 14: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

14

Verwachte lengte van lijstje

• Aannames:– Uniforme verdeling over waar elementen in de

hashtabel komen– Onafhankelijkheid

• Als we n elementen in de hashtabel zetten en we hebben m posities in de tabel:– Verwacht n/m elementen voor de lengte van

een element in de tabel

Page 15: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

15

Analyse

• Schrijf n(j) is aantal keys op positie j = lengte gelinkte lijst T(j)

• Onder de simple uniform hashing aanname is de verwachte waarde van n(j):– E(n(j)) = n/m

Stelling. In een hashtabel waarbij botsingen door chaining worden opgelost, onder de simple uniform hashing aanname, kost een onsuccesvolle zoekactie gemiddeld (1+n/m) tijd

Bewijs. (1) om h(key) te berekenen, en (1+n/m) om lijst af te lopen, want verwachtte lengte van de lijst is n/m.

n/m is de ‘loadfactor’, en wordt met genoteerd

Page 16: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

16

Succesvolle zoekacties kosten evenveel (maar lastiger bewijs)

Stelling. In een hashtabel waarbij botsingen door chaining worden opgelost, onder de simple uniform hashing aanname, kost een succesvolle zoekactie gemiddeld (1+n/m) tijd

Bewijs (schets). Neem aan dat elk van de n elementen evenveel kans heeft om gezocht te worden.Gemiddeld zoek je de helft van de lijst T(h(key)) langsElk van de andere n-1 elementen heeft kans 1/m (onafhankelijk) om in

dezelfde lijst te staanDus de verwachtte lengte van T(h(key)) is 1+ (n-1)/m Verwachtte tijd: (1 + (1/2)*(1+(n-1)/m))) = (1+n/m).

(Iets rigoureuzer bewijs in boek.)• Conclusie: als je tabellen gebruikt met n = O(m), dan is de

verwachtte tijd (onder aanname): (1).

Page 17: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

17

Hashfuncties: maak van elke key een integer

• Keys kan je zien als bitstrings, en die kan je zien als integers

• Dus, we nemen aan dat de keys integers zijn

• Slechte hashfunctie:– Eerste r bits van de key– Want dan botsen keys met hetzelfde

beginstuk

Page 18: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

18

Hash-functies: 2 methoden

• Division method: (“deel-methode”)– h(k) = k mod m

• Multiplication method: (“vermenigvuldig-methode”)– h(k) = m( kA – kA )– Voor constant A met 0 < A < 1– Dus: vermenigvuldig met geschikt getal tussen 0 en 1, neem het deel

“achter de komma”, en vermenigvuldig met m en rond naar beneden af

– Voordeel: hangt niet zo erg af van keuze van m, en dus kan je je tabelgrootte zelf kiezen

– Beste keuze van A??? • Knuth: neem A = ( 5 – 1)/ 2 = 0.61803…

Geval:registratie nummers

en moduli …

Geval:registratie nummers

en moduli …

Page 19: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

19

Open addressing

• Alle elementen opslaan in de tabel zelf• Idee:

– Hashfunctie heeft twee argumenten:• Key• Aantal “eerdere pogingen”

• Methode:– Reken eerst h(k,0) uit– Als h(k,0) leeg is, zetten we k op positie h(k,0),– Als er wel wat op h(k,0) staat, dan rekenen we h(k,1) uit– Als h(k,1) leeg is, zetten we k op positie h(k,1)– Anders, kijk naar h(k,2), etc.

Page 20: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

20

Open addressing pseudocode en aanname

• Aanname: voor elke key k geldt: elke positie in {0, 1, 2, …, m-1} komt precies 1 keer voor in de “probe sequence” {h(k,0), h(k,1), h(k,2), …, h(k,m)}

• Goede “schudding” van de permutatie gewenst

Hash-Insert(T,k)• i = 0• while h(k,i) niet leeg and i<m do

– i++;• if i<m then

– Zet k op positie h(k,i)• else

– Return foutmelding: Tabel te vol!!!!

Page 21: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

21

Zoeken pseudocode

Hash-Search(T,k)• i=0;• repeat

– positie = h(k,i);– if k staat in T(positie) then

• Return extra gegevens op T(positie) etc. Gevonden!

– i++;

• until T[positie] == NIL (lege plek) or i == m• return Element niet gevonden (NIL)

Page 22: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

22

Weglaten – het probleem

• Probleem: – “Gewoon” weglaten kan misgaan:

• Stel h(x,0) = h(y,0) = 10

• We slaan x op, op positie 10

• We slaan y op. h(y,0) is vol, dus y gaat naar h(y,1), zeg 20

• Nu laten we x weg

• Nu zoeken we y, en we kijken eerst op 10. Maar… daar staat niks meer!

Page 23: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

23

Weglaten – gedeeltelijke oplossing

• Oplossing:– Na weglaten krijg je niet een “gewone” positie, maar een positie met

een speciale DELETED waarde– Zoeken: doorzoeken als je DELETED ziet, totdat je ‘t element vindt

of LEGE positie tegenkomt– Invoegen: zet op de eerst gevonden plaats met LEEG of met

DELETED– Nadeel: weggelaten elementen beïnvloeden nog steeds de tijd van

zoekacties– Techniek: herbouw de hele hash-tabel als er “teveel” deletions

gedaan zijn:• Maak een nieuwe lege tabel• Zet alle “echte” elementen over naar de nieuwe tabel• Gooi de oude tabel weg

• Of gebruik Chaining als je deletions wil doen

Page 24: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

24

Keuze van hashfuncties voor open addressing

• Stel h’ is “gewone” hashfunctie (met 1 argument)• Overzicht (details komen):

– Linear probing• h(k,i) = (h’(k)+i) mod m

– Quadratic probing• h(k,i) = (h’(k) + c1 i+ c2 i2) mod m

– Double hashing• h(k,i) = (h’(k) + i* h’’(k)) mod m

Page 25: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

25

Linear probing

• h(k,i) = (h’(k)+i) mod m

• Nadeel: primary clustering (“primaire klontvorming”): ophopen van keys bij elkaar als hun hashwaarden in elkaars buurt zitten: lange zoek- en invoegtijden

Page 26: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

26

Quadratic probing

• h(k,i) = (h’(k) + c1 i + c2 i2) mod m

• Voor geschikte constantes c1 en c2

• Geen primaire klontvorming, maar wel secundaire klontvorming: alleen gevolgen voor keys met dezelfde hashwaarde – O(1) verwacht…

Page 27: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

27

Double hashing

• Stel h’ is een “gewone” hashfunctie (met 1 argument)• Stel h’’ is een functie die altijd elementen in 1 … m-1 geeft die

relatief priem tov m zijn• Double hashing

– h(k,i) = (h’(k) + i* h’’(k)) mod m• Bijvoorbeeld:

– m is macht van 2– h’’ geeft oneven getal

• Of:– Neem m priem, en getal m’ die iets kleiner is dan m, bijv m’=m-1– h’(k) = k mod m;– h’’(k) = 1+ (k mod m’)

• Double hashing benadert de simple uniform hashing aanname het beste

Page 28: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

28

Analyse

• Neem weer uniform hashing aanStelling. In een hash-tabel waarbij botsingen door open

addressing worden opgelost, onder de simple uniform hashing aanname, kost een onsuccesvolle zoekactie gemiddeld (1+1/(1-)) tijd, waarbij = n/m < 1.

BewijsDe kans dat er een element op positie h(k,0) staat is . De kans dat we

daarna de tweede keer een bezette positie zien is (n-1)/(m-1), want de 2e plek heeft m-1 mogelijkheden waar nog n-1 elementen zitten. Zo is de kans dat we minstens i keer een positie bekijken met een element erop:

i

m

n

im

in

m

n

m

n

m

n

1

1*...*

2

2*

1

1*

Page 29: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

29

Analyse - vervolg• Kans dat je ‘n i-de positie bekijkt is hooguit i-1. Dus verwachtte aantal

posities dat je bekijkt is hooguit

• Verwachtte tijd is O(1+ aantal bekeken posities) = O(1 + 1/(1-n/m)). QED

• Als loadfactor constant is, betekent dit dat de verwachtte tijd (onder aanname over hashfunctie) O(1) is: constant.

• Bijvoorbeeld: als tabel voor 50% vol: 1/(1-0.5) = 2 posities; als tabel voor 90% vol: 1/(1-0.9) = 10 posities die gemiddeld bekeken worden.

1

1

01

1

j

jm

i

i

Page 30: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

30

Toevoegen: analyse

Stelling. In een hashtabel waarbij botsingen door open addressing worden opgelost, onder de simple uniform hashing aanname, kost een insertion gemiddeld (1+1/(1-)) tijd, waarbij = n/m < 1.

Bewijs: we doen eerst een onsuccesvolle zoekactie op het in te voegen element, en dan plaatsen we het element. Dus, de vorige analyse geldt.

Page 31: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

31

Analyse van succesvolle zoekactie

Stelling. In een hashtabel waarbij botsingen door open addressing worden opgelost, onder de simple uniform hashing aanname, kost een succesvolle zoekactie gemiddeld (1+(1/) ln (1/(1-)) tijd, waarbij =n/m < 1.

Bewijs. Stel k is het (i+1)e element dat we invoegen.Als we ‘m zoeken, kunnen we alleen het 1e, 2e, …, ie element dat

ingevoegd is tegenkomen, want k kan alleen met hun botsen tijdens de insertion van k.

Verwachtte aantal bekeken posities bij zoeken van k is daarom hooguit 1/(1-i/m) = m / (m-i).

Gemiddeld over 1e, 2e, …, ne element is:

Hierbij nemen we aan dat elk element dezelfde kans heeft om gezocht te worden; details zie boek.

1

0 1

1ln

1...*

1 n

i im

m

n

Page 32: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

32

Succesvolle zoekacties

• Voor constante loadfactor: succesvol zoeken kost O(1) tijd

• Bijvoorbeeld: als tabel 50% vol, dan 1.387 posities bekeken; 90% vol geeft 2.559.

• Dus: neem bij hashtabellen de tabel groot genoeg, om e.e.a. snel genoeg te laten verlopen.

Page 33: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

33

Techniek in praktijk

• We beginnen met een niet al te grote tabel• Als de load factor te groot wordt (bijv. meer

dan 0.8) dan verdubbelen we de tabelgrootte– Neem een twee keer zo groot array– Zet alle elementen uit de hashtabel in de nieuwe

array– Gebruik vanaf nu het nieuwe array– Herhalen als de load factor weer te groot wordt

Page 34: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

34

Voordelen en nadelen

• Hashtabellen hebben een slecht “slechtste geval”, maar zijn verwacht, en in de praktijk, heel snel

• Je moet een hashfunctie maken, iets doen met deletions als je open addressing gebruikt, iets doen met volle tabellen (herbouw), …

• Zoekbomen hebben meer functies: minimum, opvolger, … Als je dit soort functies wilt, is een zoekboom beter. Zo niet, dan is hashing in de praktijk meestal sneller.

Page 35: 1 Hashtabellen Datastructuren. 2 Dit onderwerp Direct-access-tabellen Hashtabellen –Oplossen van botsingen met “ketens” (chaining) –Analyse –Oplossen

35

Conclusies

• Hashtabellen: snel en praktisch• Chaining• Open adressing: het probleem zijn de deletions• Je moet goede hashfuncties maken• De tabel moet niet te vol worden, want dan wordt de

hashing te langzaam• In Java: HashMap

– Iteration over alle elementen gaat alle tabelentries langs en slaat de lege over.

– Je kan de initiële capaciteit zetten (beïnvloedt efficiëntie)

• In C#: Hashtable