Wie vermeide ich kaskadierende Größenänderungen beim Ändern der Größe von Hash-Tabellen?


8

Bei herkömmlichen Kollisionsauflösungsmethoden wie separater Verkettung und linearer / quadratischer Abtastung kann die Sondensequenz für einen Schlüssel beliebig lang sein - sie wird einfach mit hoher Wahrscheinlichkeit kurz gehalten, indem der Lastfaktor der Tabelle niedrig gehalten wird. Kollisionen während des Aufwärmens sind daher kein Problem, da sie den Lastfaktor nicht beeinflussen.

Bei Kuckuck-Hashing (und anderen Methoden, die eine O (1) -Nachschlagzeit im ungünstigsten Fall bieten?) Muss jedoch eine Größenänderung erfolgen , wenn die Prüfsequenz für einen Schlüssel zu lang wird. Wenn die Schlüssel jedoch während des erneuten Aufwärmens gemischt werden, kann es sein, dass sie eine zu lange Prüfsequenz für einen Schlüssel erstellen und eine weitere Größenänderung erfordern - möglicherweise mehrere, wenn dies mehrmals hintereinander geschieht. Die Wahrscheinlichkeit ist gering, besonders bei einer guten Hash-Funktion, aber ich habe gesehen, dass es passiert.

Gibt es eine Möglichkeit - ohne explizit eine perfekte Hash-Funktion während des Wiederaufbereitens zu generieren - sicherzustellen, dass Größenänderungen nicht auf diese Weise kaskadieren können? Möglicherweise spezifisch für ein bestimmtes Kollisionsauflösungsschema? Die Literatur, auf die ich bisher gestoßen bin, scheint die Sache völlig zu beschönigen. Denken Sie daran, dass ich auch daran interessiert bin, Hash-Tabellen zu verkleinern und nicht nur zu vergrößern.

Antworten:


1

Sie fragen, wie Sie kaskadierende Wiederholungen vermeiden können, haben die Antwort jedoch bereits in Ihrem Beitrag angegeben. Sie halten die Wahrscheinlichkeit, dass schlechte Ereignisse auftreten, gering.

Da erwähnen Sie Kuckuck Hashing. Die Wahrscheinlichkeit, dass Sie eine lange Prüfsequenz erhalten, beträgt . Wenn Sie also erneut aufwärmen, fügen Sie Elemente von Grund auf neu ein. Die Wahrscheinlichkeit, dass die Wiederaufbereitung nicht erfolgreich ist, beträgt dann , sodass Sie mit sehr hoher Wahrscheinlichkeit erfolgreich sind. In Erwartung benötigen Sie nur eine konstante Anzahl von Versuchen. Wenn Sie feststellen, dass Sie Probleme beim erneuten Aufwärmen haben, sollten Sie die Tabellengröße erhöhen und den Auslastungsfaktor ändern. Alternativ können Sie eine bessere Familie von Hash-Funktionen auswählen.n O ( 1 / n )O(1/n2)nO(1/n)


-1

Ich glaube, ich habe eine Lösung, die vom linearen Hashing inspiriert ist :

Wenn die Hash-Funktion (en) konstant gehalten werden (dh beim Ändern der Größe nicht geändert werden) und die Tabelle immer durch Verdoppeln der Slots vergrößert wird, gilt dies nach dem Wachstum der Tabelle

Hmod2L={HmodL+LorHmodL

Dabei ist der Hash eines Schlüssels und die alte Anzahl von Slots. Dies bedeutet, dass ein Schlüssel entweder dort bleibt, wo er ist, oder sich in einen eindeutigen Steckplatz im neu zugewiesenen Bereich bewegt, der garantiert leer ist.HL

Um dies auf (d-ary) Kuckuck-Hashing anzuwenden, ändern Sie einfach die Größe jeder Untertabelle einzeln und verschieben Sie die Tasten nicht zwischen den Untertabellen.

Um die Tabelle zu verkleinern, müssen Sie bestätigen, dass ist Für jeden Schlüssel in der Tabelle frei, und wenn ja, verschieben Sie sie alle in ihre -Slots. Dies ist natürlich ... Ich bin mir nicht sicher, ob es einen besseren Weg gibt, als die Prüfung für jede Löschung durchzuführen, sobald der Ladefaktor unter die Hälfte fällt.{HmodL2+L2, HmodL2}HmodL2O(n)


Ich bin mir nicht sicher, ob das funktioniert. Was ist, wenn Ihre Hash-Funktion für eine Konstante c h (x) = c ist?
jbapple
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.