Haftungsausschluss: Ich weiß, dass es hier und bei Stackoverflow bereits ähnlich klingende Fragen gibt. Aber es geht nur um Kollisionen, was ich nicht verlange.
Meine Frage ist: Warum ist kollisions weniger Nachschlagen O(1)
in erster Linie?
Nehmen wir an, ich habe diese Hashtabelle:
Hash Content
-------------
ghdjg Data1
hgdzs Data2
eruit Data3
xcnvb Data4
mkwer Data5
rtzww Data6
Jetzt suche ich nach dem Schlüssel, k
den die Hash-Funktion h(k)
gibt h(k) = mkwer
. Aber woher "weiß" die Suche, dass sich der Hash mkwer
auf Position 5 befindet? Warum muss es nicht durch alle Tasten scrollen O(n)
, um es zu finden? Die Hashes können keine echten Hardwareadressen sein, da ich die Fähigkeit verlieren würde, die Daten zu verschieben. Und soweit ich weiß, ist die Hashtabelle nicht nach den Hashes sortiert (selbst wenn dies der Fall wäre, würde die Suche auch dauern O(log n)
)?
Wie hilft es, einen Hash zu kennen, um den richtigen Platz in der Tabelle zu finden?
Die Hash-Funktion berechnet die Array-Position aus der angegebenen Zeichenfolge . Wenn dies ein perfekter Hash ist, bedeutet dies, dass es mit Sicherheit keine Kollisionen gibt. Das Array ist höchstwahrscheinlich mindestens doppelt so groß wie die Anzahl der Elemente.
Dieser sehr einfache Hash (begrenzt und anfällig für Kollisionen) unterscheidet sich von anderen Hashes im Hashing-Mechanismus und berücksichtigt keine gegebenen Eingaben. In einem fortgeschritteneren Schema ist der Hash eine größere Anzahl, angepasst an die Anzahl der Elemente. Für alle Eingaben wird ein perfekter Hash generiert, um keine Kollisionen zu gewährleisten.
quelle
Um die Antwort von David Richerby zu erweitern, ist der Begriff " Hash-Funktion " etwas überladen. Wenn wir über eine Hash-Funktion sprechen, denken wir oft an MD5, SHA-1 oder etwas wie Javas
.hashCode()
Methode, die einige Eingaben in eine einzelne Zahl umwandelt. Es ist jedoch sehr unwahrscheinlich, dass die Domäne dieser Nummer (dh der Maximalwert) dieselbe Größe hat wie die Hashtabelle, in der Sie Daten speichern möchten (MD5 ist 16 Byte, SHA-1 ist 20 Byte und.hashCode()
istint
-4 Bytes).Ihre Frage bezieht sich also auf diesen nächsten Schritt: Wenn wir eine Hash-Funktion haben, die beliebige Eingaben auf Zahlen abbilden kann, wie fügen wir sie in eine Datenstruktur einer bestimmten Größe ein? Mit einer anderen Funktion, auch "Hash-Funktion" genannt!
Ein triviales Beispiel für eine solche Funktion ist Modulo ; Mit Modulo können Sie einem bestimmten Index in einem Array auf einfache Weise eine beliebige Anzahl beliebiger Größen zuordnen. Dies wird in CLRS als "Teilungsmethode" eingeführt:
Java
HashMap
verwendet eine modifizierte Version der Divisionsmethode, die einen Vorverarbeitungsschritt ausführt, um schwache.hashCode()
Implementierungen zu berücksichtigen , sodass Arrays mit einer Potenz von zwei verwendet werden können. Sie können genau sehen, was in der.getEntry()
Methode passiert (Kommentare sind meine):Java 8 brachte eine Umschreibung mit sich,
HashMap
die noch schneller, aber etwas schwerer zu lesen ist. Es verwendet jedoch das gleiche allgemeine Prinzip für die Indexsuche.quelle