Wat is Hashtabel (hash table)?

Datastructuur die met een hashfunctie uit een sleutel een opslagpositie berekent, waardoor zoeken, invoegen en verwijderen gemiddeld O(1) kosten. Botsingen, waarbij verschillende sleutels op dezelfde positie uitkomen, worden afgehandeld met chaining of open adressering.

Japanse benaming: ハッシュテーブル

“Hashtabel (hash table)” komt voor in 7 oefenvragen uit 4 onderwerpen, bijv. Datastructuren en algoritmen, Kansrekening, statistiek en wachtrijen, Geheugenhiërarchie en prestaties.

Vakgebied: Datastructuren en algoritmen

Werking en afhandeling van botsingen

Een hashtabel zet een sleutel met een hashfunctie om in een geheel getal en gebruikt bijvoorbeeld de rest bij deling door de tabelgrootte als opslagpositie. Er zijn veel meer mogelijke sleutels dan posities, dus botsingen, waarbij verschillende sleutels op dezelfde positie uitkomen, zijn onvermijdelijk. Chaining koppelt de elementen op dezelfde positie aan elkaar, bijvoorbeeld in een gelinkte lijst. Open adressering zoekt een andere vrije positie in de tabel, met methoden zoals lineair proberen, dat de naburige posities één voor één onderzoekt, of dubbele hashing, dat met een tweede hashfunctie de stapgrootte kiest.

Bezettingsgraad en rehashing

Het aantal opgeslagen elementen gedeeld door de tabelgrootte heet de bezettingsgraad (load factor). Bij chaining is de gemiddelde lijstlengte evenredig met de bezettingsgraad; bij open adressering neemt het aantal pogingen om een vrije plaats te vinden sterk toe als de bezettingsgraad 1 nadert. Overschrijdt de bezettingsgraad een gekozen grens, dan wordt de tabel daarom vergroot, meestal tot ongeveer het dubbele, en worden alle elementen opnieuw ingevoegd (rehashing). Eén rehash kost O(n), maar omdat de tussenpozen tussen vergrotingen steeds verdubbelen, blijven de kosten per invoeging geamortiseerd O(1).

Prestaties en aandachtspunten

Het gemiddelde van O(1) veronderstelt dat de hashfunctie de sleutels gelijkmatig over de tabel spreidt. Een slechte hashfunctie, of invoer die opzettelijk botsingen veroorzaakt (een hash-floodingaanval), kan de tabel in het slechtste geval vertragen tot O(n); daarom gebruiken webservers en vergelijkbare software hashfuncties die met een willekeurige seed worden gemengd. Een hashtabel houdt haar elementen bovendien niet op volgorde, dus binaire zoekbomen of B-bomen zijn beter geschikt voor bereikzoekopdrachten en geordende opsommingen. De werkelijke snelheid hangt ook af van het cachegedrag: methoden die naburige posities onderzoeken, zoals lineair proberen, zijn vaak sneller dan chaining, dat pointers volgt.

Nu oefenen: vragen over Hashtabel (hash table)

Tien sleutels worden opgeslagen in een hashtabel met 100 buckets. Elke sleutel wordt onafhankelijk van de andere en met gelijke kans aan een van de 100 buckets toegewezen. Wat is de verwachtingswaarde van het aantal paren sleutels dat aan dezelfde bucket wordt toegewezen?

  1. A0,1
  2. B0,45
  3. C0,9
Antwoord en toelichting tonen

Antwoord: B. 0,45

Er zijn 10C2 = 45 paren sleutels, en elk paar komt met kans 1/100 in dezelfde bucket terecht. Door de lineariteit van de verwachtingswaarde (de verwachtingswaarde van een som is de som van de verwachtingswaarden) is de verwachtingswaarde van het aantal paren in dezelfde bucket 45 × 1/100 = 0,45. De lineariteit van de verwachtingswaarde geldt ook als de paren niet onafhankelijk zijn, dus de kansen van de paren kunnen eenvoudig worden opgeteld.

Welke beschrijving van een botsing (collision) in een hashtabel is juist?

  1. AUit een hashwaarde kan de oorspronkelijke sleutel worden afgeleid
  2. BVerschillende sleutels leveren dezelfde hashwaarde (opslagpositie) op
  3. CDezelfde sleutel levert bij elke uitvoering een andere hashwaarde op
Antwoord en toelichting tonen

Antwoord: B. Verschillende sleutels leveren dezelfde hashwaarde (opslagpositie) op

Een hashtabel is een datastructuur die met een hashfunctie uit de sleutel een opslagpositie berekent, waardoor zoeken, invoegen en verwijderen gemiddeld O(1) kosten. Er zijn veel meer mogelijke sleutels dan posities in de tabel, dus dat verschillende sleutels op dezelfde positie uitkomen (een botsing), is onvermijdelijk. Botsingen worden daarom afgehandeld met methoden zoals chaining, die de elementen op dezelfde positie tot een lijst koppelt, of open adressering, die een andere vrije positie zoekt. Dezelfde sleutel moet altijd dezelfde hashwaarde opleveren, anders kan er niet worden gezocht. Of de sleutel uit de hashwaarde kan worden afgeleid, is een eigenschap die bij cryptografisch gebruik telt en heeft niets met botsingen te maken.

Veelgestelde vragen

Hoe hangen hashtabellen samen met hashfuncties?

Een hashfunctie berekent uit een sleutel een waarde in een vast bereik, en een hashtabel is een datastructuur die haar gebruikt om opslagposities te berekenen. Hashfuncties voor hashtabellen leggen de nadruk op snelheid en een gelijkmatige spreiding en hoeven meestal niet eenrichtings te zijn zoals cryptografische hashfuncties.

Waar worden hashtabellen gebruikt?

Overal waar waarden snel op sleutel moeten worden opgezocht, zoals dictionary's (associatieve arrays) en sets in programmeertalen, symbooltabellen in compilers, hash joins en hashindexen in databases, en cachebeheer.

“Hashtabel (hash table)” in de toelichting

Vragen met “Hashtabel (hash table)” (7)

  1. Tien sleutels worden opgeslagen in een hashtabel met 100 buckets. Elke sleutel wordt onafhankelijk van de andere en met gelijke kans aan een van de 100 buckets toegewezen. Wat is de verwachtingswaarde van het aantal paren sleutels dat aan dezelfde bucket wordt toegewezen?
  2. Welke beschrijving van een botsing (collision) in een hashtabel is juist?
  3. De sleutels 10, 17, 24 en 3 worden in deze volgorde opgeslagen in een hashtabel van grootte 7 (posities 0 tot 6) met de hashfunctie h(k) = k mod 7. Botsingen worden opgelost met lineair proberen (linear probing): de positie schuift telkens één plaats op (na 6 komt 0) tot er een vrije plaats is gevonden. Op welke positie wordt sleutel 3 opgeslagen?
  4. Welke vergelijking van chaining (de elementen op dezelfde positie aan elkaar koppelen in een gelinkte lijst) en open adressering (een andere vrije positie in de tabel zoeken) als methoden om botsingen in een hashtabel af te handelen is juist? De bezettingsgraad (load factor) is het aantal opgeslagen elementen gedeeld door de grootte van de tabel.
  5. Wat is de meest passende reden dat open adressering met lineair proberen bij een hashtabel met veel elementen en een bezettingsgraad van ongeveer 0,5 vaak sneller is dan chaining (elementen koppelen met gelinkte lijsten)?
  6. Bij welke toegang is hardware-prefetching bijzonder effectief?
  7. Welke vergelijking van 'grofkorrelige locks', waarbij een grote datastructuur als geheel door één lock wordt beschermd, en 'fijnkorrelige locks', waarbij delen elk door een eigen lock worden beschermd, is juist?

Verwante termen

Gelinkte lijst (linked list) Hashfunctie Prefetching Verwachtingswaarde Modulo-operatie Cacheregel (cache line) Pointer Tijdcomplexiteit (O-notatie) Array Algoritme van Dijkstra

Naar de woordenlijst