Doppel-Hashing

Beim Doppelstreuwertverfahren oder Doppel-Hashing (englisch double hashing) handelt es sich um eine Methode zur Realisierung eines geschlossenen Hash-Verfahrens. In geschlossenen Hash-Verfahren wird versucht, Überläufer in der Hash-Tabelle unterzubringen, anstatt sie innerhalb der Zelle (z. B. als Liste) zu speichern. (Offene Hash-Verfahren können Einträge doppelt belegen und benötigen daher keine Sondierung.) Achtung: Wie es im Artikel Hashtabelle unter „Varianten des Hashverfahrens“ steht, werden die Bezeichnungen „offenes“ bzw. „geschlossenes Hashing“ auch in genau umgekehrter Bedeutung verwendet.

Um dies umzusetzen, verwendet man beim Doppel-Hashing eine Sondierungsfunktion, die eine sekundäre Hash-Funktion beinhaltet, z. B. s ( j , k ) := j h ( k ) {\displaystyle \;s(j,k):=j\cdot h'(k)} , und die angewendet wird, falls der durch die primäre Hash-Funktion h ( k ) {\displaystyle \;h(k)} berechnete Index bereits besetzt ist.

Die vollständige Hash-Funktion lautet dann: h ( k ) s ( j , k ) {\displaystyle \;h(k)-s(j,k)} , wobei j die Anzahl bereits „ausprobierter“ Indizes ist, d. h., dass j jedes Mal um 1 erhöht wird, wenn ein Index bereits belegt ist.

Die Sondierungsfunktion s ( j , k ) {\displaystyle \;s(j,k)} soll dabei eine Permutation der Indizes der Hash-Tabelle bilden.

Die Folge von Hash-Funktionen, die nun mittels h {\displaystyle h} und h {\displaystyle h'} gebildet werden, sieht so aus:

h j ( k ) = ( h ( k ) + h ( k ) j )   mod   m {\displaystyle h_{j}(k)=(h(k)+h'(k)\cdot j)~{\bmod {~}}m}

Die Kosten für diese Methode sind nahe den Kosten für ein ideales Hashing.

Unabhängigkeit der Hashfunktionen

Beim Doppel-Hashing werden zwei unabhängige Hash-Funktionen h {\displaystyle h} und h {\displaystyle h'} angewandt. Diese heißen unabhängig, wenn die Wahrscheinlichkeit für eine sogenannte Doppelkollision, d. h. h ( k ) = h ( y ) h ( k ) = h ( y ) {\displaystyle h(k)=h(y)\land h'(k)=h'(y)} , kleiner gleich 1 / m 2 {\displaystyle 1/m^{2}} und damit minimal ist, wobei m {\displaystyle m} die Größe des Arrays ist.

Beispiele

Beispielfunktionen

Größe des Arrays: m

Indizes: {0; m-1}

Primäre Hash-Funktion: h ( k ) := k mod m {\displaystyle h(k):=k\;{\bmod {\;}}m} (Divisions-Rest-Methode)

Sekundäre Hash-Funktion: h ( k ) := k mod ( m 2 ) + 1 {\displaystyle \;h'(k):=k\;{\bmod {\;}}(m-2)+1}

Sondierungsfunktion: s ( j , k ) := j ( k mod ( m 2 ) + 1 ) {\displaystyle \;s(j,k):=j\cdot (k\;{\bmod {\;}}(m-2)+1)}

Vollständige Doppel-Hash-Funktion: h j ( k ) := ( k mod m + j ( k mod ( m 2 ) + 1 ) ) mod m {\displaystyle \;h_{j}(k):=(k\;{\bmod {\;}}m+j\cdot (k\;{\bmod {\;}}(m-2)+1)){\bmod {m}}}

Berechnungsbeispiel

Größe des Arrays: m = 7

Hashfunktionen
h ( k ) := k mod 7 {\displaystyle h(k):=k\;{\bmod {\;}}7}
h ( k ) := k mod 5 + 1 {\displaystyle h'(k):=k\;{\bmod {\;}}5+1}
Sondierungsfunktion
h j ( k ) := ( h ( k ) + j h ( k ) ) mod m {\displaystyle h_{j}(k):=(h(k)+j\cdot h'(k))\;{\bmod {\;}}m}

Hashtabelle:

k 10 19 31 22 14 16
h 3 5 3 1 0 2
h' 1 5 2 3 5 2

Das mit Hilfe von Hashtabelle und Sondierungsfunktion gefüllte Array:

0 1 2 3 4 5 6
31 22 16 10 - 19 14

Erklärung am Beispiel k = 31 {\displaystyle k=31} :

k = 10 {\displaystyle k=10} sowie k = 19 {\displaystyle k=19} erzeugen keine Kollision und benötigen deshalb nicht die Doppel-Hash-Funktion h j {\displaystyle h_{j}} . Der Index der Hash-Funktion h {\displaystyle h} kann hier abgelesen werden. k = 31 {\displaystyle k=31} erzeugt eine Kollision im Array an der Stelle 3 {\displaystyle 3} , weshalb man nun die Doppel-Hash-Funktion h j {\displaystyle h_{j}} mit j = 1 {\displaystyle j=1} :

h 1 ( 31 ) = ( h ( 31 ) + 1 h ( 31 ) ) mod 7 ( 3 + 1 2 ) mod 7 5 mod 7 5 {\displaystyle h_{1}(31)=(h(31)+1\cdot h'(31))\;{\bmod {\;}}7\equiv (3+1\cdot 2)\;{\bmod {\;}}7\equiv 5\;{\bmod {\;}}7\equiv 5}

Die Stelle 5 {\displaystyle 5} erzeugt wieder eine Kollision, weshalb h j {\displaystyle h_{j}} nun mit j = 2 {\displaystyle j=2} aufgerufen wird:

h 2 ( 31 ) = ( h ( 31 ) + 2 h ( 31 ) ) mod 7 ( 3 + 2 2 ) mod 7 7 mod 7 0 {\displaystyle h_{2}(31)=(h(31)+2\cdot h'(31))\;{\bmod {\;}}7\equiv (3+2\cdot 2)\;{\bmod {\;}}7\equiv 7\;{\bmod {\;}}7\equiv 0}

Die Stelle 0 {\displaystyle 0} ist frei und erhält somit den Inhalt 31 {\displaystyle 31} .

Weblinks

  • Geschlossenes Hashing
  • Offenes Hashing