Hash-Tabelle

In der Informatik, einer Hash-Tabelle oder Kuddelmuddel-Karte ist eine Datenstruktur, die eine Kuddelmuddel-Funktion verwendet, sich identifizierende Werte kartografisch darzustellen, die als Schlüssel (z.B, ein Name einer Person), zu ihren verbundenen Werten (z.B, ihrer Telefonnummer) bekannt sind. So führt eine Hash-Tabelle eine assoziative Reihe durch. Die Kuddelmuddel-Funktion wird verwendet, um den Schlüssel in den Index (das Kuddelmuddel) eines Reihe-Elements umzugestalten (das Ablagefach oder der Eimer), wo der entsprechende Wert gesucht werden soll.

Ideal sollte die Kuddelmuddel-Funktion jeden möglichen Schlüssel zu einem einzigartigen Ablagefach-Index kartografisch darstellen, aber dieses Ideal ist in der Praxis selten erreichbar (wenn die Kuddelmuddel-Schlüssel nicht befestigt werden; d. h. neue Einträge werden zum Tisch nie hinzugefügt, nachdem er geschaffen wird). Statt dessen nehmen die meisten Hash-Tabelle-Designs an, dass Kuddelmuddel-Kollisionen — verschiedene Schlüssel, die zu demselben Kuddelmuddel-Wert kartografisch darstellen — vorkommen werden und irgendwie angepasst werden müssen.

In einer gut dimensionierten Hash-Tabelle sind die durchschnittlichen Kosten (Zahl von Instruktionen) für jeden lookup der im Tisch versorgten Zahl der Elemente unabhängig. Viele Hash-Tabelle-Designs erlauben auch willkürliche Einfügungen und Auswischen von Schlüsselwert-Paaren, am unveränderlichen Durchschnitt (tatsächlich, amortisiert) Kosten pro Operation.

In vielen Situationen erweisen sich Hash-Tabellen, effizienter zu sein, als Suchbäume oder jeder andere Tisch lookup Struktur. Deshalb werden sie in vielen Arten der Computersoftware, besonders für assoziative Reihe, Datenbankindexieren, geheime Lager und Sätze weit verwendet.

Kuddelmuddel-Funktion

Am Herzen der Hash-Tabelle ist der Algorithmus eine einfache Reihe von Sachen; das wird häufig einfach die Hash-Tabelle genannt. Hash-Tabelle-Algorithmen berechnen einen Index vom Datenartikel-Schlüssel und verwenden diesen Index, um die Daten in die Reihe zu legen. Die Durchführung dieser Berechnung ist die Kuddelmuddel-Funktion:

Index = f (Schlüssel, arrayLength)

Die Kuddelmuddel-Funktion rechnet innerhalb der Reihe von den Daten. ist die Größe der Reihe.

Für die Zusammenbau-Sprache oder anderen auf niedriger Stufe Programme kann eine triviale Kuddelmuddel-Funktion häufig einen Index mit gerade einer oder zwei Reihenmaschineninstruktionen schaffen.

Die Auswahl einer guten Kuddelmuddel-Funktion

Eine gute Kuddelmuddel-Funktion und Durchführungsalgorithmus sind für die gute Hash-Tabelle-Leistung notwendig, aber können schwierig sein zu erreichen.

Eine grundlegende Voraussetzung ist, dass die Funktion eine Rechteckverteilung von Kuddelmuddel-Werten zur Verfügung stellen sollte. Ein ungleichförmiger Vertrieb steigert die Zahl von Kollisionen und die Kosten der Auflösung von ihnen. Gleichförmigkeit ist manchmal schwierig, durch das Design zu sichern, aber kann empirisch mit statistischen Tests, z.B einem chi-karierten Test von Pearson auf getrennte Rechteckverteilungen bewertet werden

Der Vertrieb muss nur für Tabellengrößen s gleichförmig sein, die in der Anwendung vorkommen. Insbesondere wenn man verwendet mit der genauen Verdoppelung und dem Halbieren von s dynamisch in der Größe anzupassen, muss die Kuddelmuddel-Funktion nur gleichförmig sein, wenn s eine Macht zwei ist. Andererseits stellen einige hashing Algorithmen gleichförmiges Kuddelmuddel nur zur Verfügung, wenn s eine Primzahl ist.

Für offene Wenden-Schemas sollte die Kuddelmuddel-Funktion auch vermeiden, sich zu sammeln, von zwei oder mehr Schlüsseln zu Konsekutivablagefächern kartografisch darzustellen. Solches Sammeln kann die Lookup-Kosten veranlassen sprunghaft anzusteigen, selbst wenn der Lastfaktor niedrig ist und Kollisionen selten sind. Wie man fordert, hat das populäre multiplicative Kuddelmuddel besonders schlechtes sich sammelndes Verhalten.

Wie man

glaubt, stellen kryptografische Kuddelmuddel-Funktionen gute Kuddelmuddel-Funktionen für jede Tabellengröße s entweder durch die modulo Verminderung oder durch die Bit-Maskierung zur Verfügung. Sie können auch passend sein, wenn es eine Gefahr von böswilligen Benutzern gibt, die versuchen, einen Netzdienst durch das Behaupten zu sabotieren, dass Bitten vorgehabt haben, eine Vielzahl von Kollisionen in den Hash-Tabellen des Servers zu erzeugen. Jedoch kann die Gefahr der Sabotage auch durch preiswertere Methoden (wie Verwendung eines heimlichen Salzes zu den Daten oder des Verwendens einer universalen Kuddelmuddel-Funktion) vermieden werden.

Einige Autoren behaupten, dass gute Kuddelmuddel-Funktionen die Lawine-Wirkung haben sollten; d. h. eine Änderung des einzelnen Bit im Eingangsschlüssel, sollte durchschnittlich, Hälfte der Bit in der Produktion betreffen. Einige populäre Kuddelmuddel-Funktionen haben dieses Eigentum nicht.

Vollkommene Kuddelmuddel-Funktion

Wenn alle Schlüssel vorzeitig bekannt sind, kann eine vollkommene Kuddelmuddel-Funktion verwendet werden, um eine vollkommene Hash-Tabelle zu schaffen, die keine Kollisionen hat. Wenn minimaler vollkommener hashing verwendet wird, kann jede Position in der Hash-Tabelle ebenso verwendet werden.

Vollkommener hashing berücksichtigt unveränderlich-maligen lookups im Grenzfall. Das ist im Gegensatz zum grössten Teil des Ankettens und offenen Wenden-Methoden, wo die Zeit für lookup durchschnittlich niedrig ist, aber (proportional zur Zahl von Einträgen) für einige Sätze von Schlüsseln sehr groß sein kann.

Kollisionsentschlossenheit

Kuddelmuddel-Kollisionen sind wenn hashing eine zufällige Teilmenge eines großen Satzes von möglichen Schlüsseln praktisch unvermeidlich. Zum Beispiel, wenn 2,500 Schlüssel hashed in eine Million Eimer sogar mit einem vollkommen gleichförmigen zufälligen Vertrieb sind, gemäß dem Geburtstag-Problem gibt es eine 95-%-Chance von mindestens zwei der Schlüssel, die hashed zu demselben Ablagefach sind.

Deshalb haben die meisten Hash-Tabelle-Durchführungen eine Kollisionsentschlossenheitsstrategie, solche Ereignisse zu behandeln. Einige allgemeine Strategien werden unten beschrieben. Alle diese Methoden verlangen, dass die Schlüssel (oder Zeigestöcke zu ihnen) im Tisch zusammen mit den verbundenen Werten versorgt werden.

Lastfaktor

Die Leistung von den meisten Kollisionsentschlossenheitsmethoden hängt direkt von der Nummer n von versorgten Einträgen nicht ab. Statt dessen hängt Leistung stark vom Lastfaktor des Tisches ab. Lastfaktor ist n/s, dem Verhältnis der Zahl von versorgten Einträgen n und der Größe s der Reihe des Tisches von Eimern gleich. Manchmal wird das den füllen Faktor genannt, weil er den Teil der s Eimer in der Struktur vertritt, die mit einem versorgter Einträge der n gefüllt werden. Mit einer guten Kuddelmuddel-Funktion ist der Durchschnitt lookup Kosten fast unveränderlich, als der Lastfaktor von 0 bis 0.7 (über den 2/3 voll) zunimmt oder so. Außer diesem Punkt, der Wahrscheinlichkeit von Kollisionen und den Kosten des Berührens von ihnen Zunahmen.

Ein niedriger Lastfaktor ist nicht besonders vorteilhaft. Da sich Lastfaktor 0, das Verhältnis von unbenutzten Gebieten in den Hash-Tabelle-Zunahmen nähert, aber es gibt nicht notwendigerweise jede Verminderung von Suchkosten. Das läuft auf vergeudetes Gedächtnis hinaus.

Das getrennte Anketten

In der Strategie, die als das getrennte Anketten, direkte Anketten oder einfach Anketten bekannt ist, ist jedes Ablagefach der Eimer-Reihe ein Zeigestock zu einer verbundenen Liste, die die Schlüsselwert-Paare dass hashed zu derselben Position enthält. Lookup verlangt Abtastung der Liste für einen Zugang mit dem gegebenen Schlüssel. Einfügung verlangt das Hinzufügen einer neuen Zugang-Aufzeichnung zu jedem Ende der Liste, die dem hashed Ablagefach gehört. Auswischen verlangt Suche der Liste und das Entfernen des Elements. (Die Technik wird auch offenen hashing genannt oder hat das Wenden geschlossen.)

Verkettete Hash-Tabellen mit verbundenen Listen sind populär, weil sie nur grundlegende Datenstrukturen mit einfachen Algorithmen verlangen, und einfache Kuddelmuddel-Funktionen verwenden können, die für andere Methoden unpassend sind.

Die Kosten einer Tabellenoperation sind die der Abtastung der Einträge des ausgewählten Eimers für den gewünschten Schlüssel. Wenn der Vertrieb von Schlüsseln genug gleichförmig ist, hängen die durchschnittlichen Kosten eines lookup nur von der durchschnittlichen Zahl von Schlüsseln pro Eimer — d. h. auf dem Lastfaktor ab.

Verkettete Hash-Tabellen bleiben wirksam, selbst wenn die Zahl von Tabelleneinträgen n viel höher ist als die Zahl von Ablagefächern. Ihre Leistung baut sich anmutiger (geradlinig) mit dem Lastfaktor ab. Zum Beispiel ist eine verkettete Hash-Tabelle mit 1000 Ablagefächern und 10,000 versorgten Schlüsseln (Lastfaktor 10) fünf bis zehnmal langsamer als ein 10,000-Ablagefächer-Tisch (Lastfaktor 1); aber noch 1000mal schneller als eine einfache folgende Liste, und vielleicht noch schneller als ein erwogener Suchbaum.

Für das getrennte Anketten ist der größte anzunehmende Unfall, wenn alle Einträge in denselben Eimer eingefügt werden, in welchem Fall die Hash-Tabelle unwirksam ist und die Kosten die der Suche der Eimer-Datenstruktur sind. Wenn der Letztere eine geradlinige Liste ist, kann das lookup Verfahren alle seine Einträge scannen müssen; so sind die Grenzfall-Kosten zur Nummer n von Einträgen im Tisch proportional.

Die Eimer-Ketten werden häufig als geordnete Listen durchgeführt, die durch das Schlüsselfeld sortiert sind; diese Wahl ungefähr Hälften der durchschnittlichen Kosten von erfolglosem lookups, im Vergleich zu einer nicht eingeordneten Liste. Jedoch, wenn einige Schlüssel viel mit größerer Wahrscheinlichkeit heraufkommen werden, als andere eine nicht eingeordnete Liste mit der heuristischen Bewegung zur Vorderseite wirksamer sein kann. Es lohnt sich, hoch entwickeltere Datenstrukturen wie erwogene Suchbäume nur zu denken, wenn der Lastfaktor (ungefähr 10 oder mehr) groß ist, oder wenn der Kuddelmuddel-Vertrieb wahrscheinlich sehr ungleichförmig sein wird, oder wenn man gute Leistung sogar in einem größten anzunehmenden Unfall versichern muss. Jedoch kann das Verwenden eines größeren Tisches und/oder einer besseren Kuddelmuddel-Funktion in jenen Fällen noch wirksamer sein.

Verkettete Hash-Tabellen erben auch die Nachteile von verbundenen Listen. Wenn er kleine Schlüssel und Werte versorgt, kann der Raum oben des Zeigestocks in jeder Zugang-Aufzeichnung bedeutend sein. Ein zusätzlicher Nachteil ist das, eine verbundene Liste überquerend, hat schlechte Leistung des geheimen Lagers, das geheime Verarbeiter-Lager unwirksam machend.

Das getrennte Anketten mit Listenköpfen

Einige Anketten-Durchführungen versorgen die erste Aufzeichnung jeder Kette in der Ablagefach-Reihe selbst. Der Zweck ist, Leistungsfähigkeit des geheimen Lagers des Hash-Tabelle-Zugangs zu vergrößern. Um Speicherraum zu sparen, haben solche Hash-Tabellen häufig fast so viele Ablagefächer wie versorgte Einträge, bedeutend, dass viele Ablagefächer zwei oder mehr Einträge haben.

Das getrennte Anketten mit anderen Strukturen

Statt einer Liste kann man jede andere Datenstruktur verwenden, die die erforderlichen Operationen unterstützt. Zum Beispiel, durch das Verwenden eines selbstbalancierenden Baums, kann die theoretische Grenzfall-Zeit von allgemeinen Hash-Tabelle-Operationen (Einfügung, Auswischen, lookup) zu O heruntergebracht werden (loggen Sie n), aber nicht O (n). Jedoch ist diese Annäherung nur der Schwierigkeiten und Extraspeicherkosten wert, wenn lange Verzögerungen um jeden Preis (z.B in einer Echtzeitanwendung) vermieden werden müssen, oder wenn man vor vielen Einträgen hashed zu demselben Ablagefach schützen muss (z.B, wenn man äußerst ungleichförmigen Vertrieb, oder im Fall von Websites oder anderen öffentlich zugänglichen Dienstleistungen erwartet, die für den böswilligen Schlüsselvertrieb in Bitten verwundbar sind).

Die Variante hat Reihe-Hash-Tabelle-Gebrauch eine dynamische Reihe genannt, um alle Einträge dass Kuddelmuddel zu demselben Ablagefach zu versorgen. Jeder kürzlich eingefügte Zugang wird am Ende der dynamischen Reihe angehangen, die dem Ablagefach zugeteilt wird. Die dynamische Reihe wird auf eine genau-passende Weise in der Größe angepasst, bedeutend, dass es nur durch so viele Bytes, wie erforderlich, angebaut wird. Wie man fand, haben alternative Techniken wie das Wachsen der Reihe durch Block-Größen oder Seiten Einfügungsleistung, aber an Kosten im Raum verbessert. Diese Schwankung macht effizienteren Gebrauch des Zentraleinheitsversteckens und der Übersetzung lookaside Puffers (TLB), weil Ablagefach-Einträge in folgenden Speicherpositionen versorgt werden. Es verzichtet auch auf die Zeigestöcke, die durch verbundene Listen erforderlich sind, der Raum spart. Trotz der häufigen Reihe in der Größe anpassende allgemeine Raumkosten, die durch das Betriebssystem wie Speicherzersplitterung übernommen sind, wurden gefunden, klein zu sein.

Eine Weiterentwicklung auf dieser Annäherung ist der so genannte dynamische vollkommene hashing, wo ein Eimer, der k Einträge enthält, als eine vollkommene Hash-Tabelle mit k Ablagefächern organisiert wird. Während es mehr Gedächtnis verwendet (n Ablagefächer für n Einträge, im Grenzfall und den n*k Ablagefächern im durchschnittlichen Fall), hat diese Variante unveränderlichen Grenzfall lookup Zeit versichert, und niedrig Zeit für die Einfügung amortisiert.

Das offene Wenden

In einer anderen Strategie, genannt das offene Wenden, werden alle Zugang-Aufzeichnungen im Eimer versorgt kleiden sich. Wenn ein neuer Zugang eingefügt werden muss, werden die Eimer untersucht, mit hashed-zu Ablagefach anfangend und in einer Untersuchungsfolge weitergehend, bis ein freies Ablagefach gefunden wird. Wenn man nach einem Zugang sucht, werden die Eimer in derselben Folge gescannt, bis entweder die Zielaufzeichnung gefunden wird, oder ein unbenutztes Reihe-Ablagefach wird gefunden, der anzeigt, dass es keinen solchen Schlüssel im Tisch gibt. Der Name "das offene Wenden" bezieht sich auf die Tatsache, dass die Position ("Adresse") des Artikels durch seinen Kuddelmuddel-Wert nicht bestimmt wird. (Diese Methode wird auch geschlossenen hashing genannt; es sollte mit "offenem hashing" nicht verwirrt sein, oder "hat das Wenden geschlossen", die gewöhnlich das getrennte Anketten bedeuten.)

Wohl bekannte Untersuchungsfolgen schließen ein:

  • Geradlinige Untersuchung, in der der Zwischenraum zwischen Untersuchungen (gewöhnlich 1) befestigt wird
  • Quadratische Untersuchung, in der der Zwischenraum zwischen Untersuchungen durch das Hinzufügen der aufeinander folgenden Produktionen eines quadratischen Polynoms zum Startwert vergrößert wird, der durch die ursprüngliche Kuddelmuddel-Berechnung gegeben ist
  • Verdoppeln Sie hashing, in dem der Zwischenraum zwischen Untersuchungen durch eine andere Kuddelmuddel-Funktion geschätzt wird

Ein Nachteil aller dieser offenen Wenden-Schemas besteht darin, dass die Zahl von versorgten Einträgen die Zahl von Ablagefächern in der Eimer-Reihe nicht überschreiten kann. Tatsächlich, sogar mit guten Kuddelmuddel-Funktionen, baut sich ihre Leistung drastisch ab, wenn der Lastfaktor darüber hinaus 0.7 wächst oder so. So passt ein aggressiverer Schema in der Größe an ist erforderlich. Getrennte sich verbindende Arbeiten richtig mit jedem Lastfaktor, obwohl Leistung wahrscheinlich angemessen sein wird, wenn es unten 2 behalten wird oder so. Für viele Anwendungen beauftragen diese Beschränkungen den Gebrauch davon, mit seinen begleitenden Kosten dynamisch in der Größe anzupassen.

Offene Wenden-Schemas stellen auch strengere Voraussetzungen an die Kuddelmuddel-Funktion: Außer dem Verteilen der Schlüssel gleichförmiger über die Eimer muss die Funktion auch das Sammeln von Kuddelmuddel-Werten minimieren, die in der Untersuchungsordnung aufeinander folgend sind. Mit dem getrennten Anketten ist die einzige Sorge, dass zu viele Gegenstände zu demselben Kuddelmuddel-Wert kartografisch darstellen; ob sie angrenzend sind oder nahe gelegen völlig irrelevant ist.

Sogar erfahrene Programmierer können finden, dass solches Sammeln hart vermeidet.

Das offene Wenden spart nur Gedächtnis, wenn die Einträge klein sind (weniger als viermal die Größe eines Zeigestocks) und der Lastfaktor nicht zu klein ist. Wenn der Lastfaktor Null nah ist (d. h. es gibt viel mehr Eimer als versorgte Einträge), das offene Wenden ist verschwenderisch, selbst wenn jeder Zugang gerade zwei Wörter ist.

Das offene Wenden vermeidet die Zeit oben, jede neue Zugang-Aufzeichnung zuzuteilen, und kann sogar ohne einen Speicherverteiler durchgeführt werden. Es vermeidet auch den Extraumweg, der erforderlich ist, auf den ersten Zugang jedes Eimers (d. h. gewöhnlich der einzige) zuzugreifen. Es hat auch bessere Gegend der Verweisung besonders mit der geradlinigen Untersuchung. Mit kleinen Rekordgrößen können diese Faktoren bessere Leistung nachgeben als das Anketten besonders für lookups.

Hash-Tabellen mit dem offenen Wenden sind auch leichter in Fortsetzungen zu veröffentlichen, weil sie Zeigestöcke nicht verwenden.

Andererseits ist das normale offene Wenden eine schlechte Wahl für große Elemente, weil diese Elemente komplette Zentraleinheitslinien des geheimen Lagers füllen (den Vorteil des geheimen Lagers verneinend), und eine große verfügbare Fläche an große leere Tabellenablagefächer vergeudet wird. Wenn der offene Wenden-Tisch nur Verweisungen auf Elemente versorgt (Außenlagerung), verwendet es Raum, der mit dem Anketten sogar für große Aufzeichnungen vergleichbar ist, aber verliert seinen Geschwindigkeitsvorteil.

Im Allgemeinen wird das offene Wenden für Hash-Tabellen mit kleinen Aufzeichnungen besser verwendet, die innerhalb des Tisches (innere Lagerung) versorgt werden und eine Linie des geheimen Lagers einfügen können. Sie sind für Elemente eines Wortes oder weniger besonders passend. Wenn, wie man erwartet, der Tisch einen hohen Lastfaktor hat, sind die Aufzeichnungen groß, oder die Daten ist variable-große, verkettete Hash-Tabellen häufig leisten ebenso oder besser.

Schließlich, verwendet vernünftig, ist jede Art des Hash-Tabelle-Algorithmus gewöhnlich schnell genug; und der Prozentsatz einer im Hash-Tabelle-Code ausgegebenen Berechnung ist niedrig. Speichergebrauch wird übermäßig selten betrachtet. Deshalb in den meisten Fällen sind die Unterschiede zwischen diesen Algorithmen geringfügige und andere Rücksichten normalerweise tritt in Spiel ein.

Verschmelzter hashing

Eine Hybride des Ankettens und offenen Wendens, hat Hashing-Verbindungen zusammen Ketten von Knoten innerhalb des Tisches selbst verschmelzt. Wie das offene Wenden erreicht es Raumgebrauch und (etwas verringert) Vorteile des geheimen Lagers gegenüber dem Anketten. Wie das Anketten stellt es sich sammelnde Effekten nicht aus; tatsächlich kann der Tisch zu einer hohen Speicherdichte effizient gefüllt werden. Verschieden vom Anketten kann es nicht mehr Elemente haben als Tabellenablagefächer.

Robin Hood hashing

Eine interessante Schwankung auf der doppelten-hashing Kollisionsentschlossenheit ist Robin Hood hashing. Die Idee besteht darin, dass ein neuer Schlüssel einen bereits eingefügten Schlüssel versetzen kann, wenn seine Untersuchungszählung größer ist als dieser des Schlüssels an der aktuellen Position. Die Nettowirkung davon besteht darin, dass es Grenzfall-Suchzeiten im Tisch reduziert. Das ist den bestellten Hash-Tabellen von Knuth ähnlich, außer dass das Kriterium, für einen Schlüssel zu stoßen, von keiner direkten Beziehung zwischen den Schlüsseln abhängt. Seitdem werden sowohl der Grenzfall als auch die Schwankung in der Zahl von Untersuchungen drastisch reduziert, eine interessante Schwankung soll forschend eindringen der Tisch, der bei der erwarteten erfolgreichen Untersuchung anfängt, schätzen und breiten sich dann von dieser Position in beiden Richtungen aus.

Äußerlicher Robin Hashing ist eine Erweiterung dieses Algorithmus, wo der Tisch in einer Außendatei versorgt wird und jede Tabellenposition einer fest-großen Seite oder Eimer mit B-Aufzeichnungen entspricht.

Kuckuck hashing

Eine andere alternative offen richtende Lösung ist Kuckuck hashing, der unveränderliche lookup Zeit mit dem Grenzfall, und unveränderliche amortisierte Zeit für Einfügungen und Auswischen sichert. Es verwendet zwei oder mehr Kuddelmuddel-Funktionen, was bedeutet, dass jedes Paar des Schlüssels/Werts in zwei oder mehr Positionen sein konnte. Für lookup wird die erste Kuddelmuddel-Funktion verwendet; wenn der Schlüssel/Wert nicht gefunden wird, dann wird die zweite Kuddelmuddel-Funktion und so weiter verwendet. Wenn eine Kollision während der Einfügung geschieht, dann wird der Schlüssel mit der zweiten Kuddelmuddel-Funktion wieder aufgewärmt, es zu einem anderen Eimer kartografisch darzustellen. Wenn alle Kuddelmuddel-Funktionen verwendet werden und es noch eine Kollision gibt, dann wird der Schlüssel, mit dem sie kollidiert hat, entfernt, um Raum für den neuen Schlüssel zu machen, und der alte Schlüssel wird mit einer der anderen Kuddelmuddel-Funktionen wieder aufgewärmt, die sie zu einem anderen Eimer kartografisch darstellt. Wenn diese Position auch auf eine Kollision, dann die Prozess-Wiederholungen hinausläuft, bis es keine Kollision gibt oder der Prozess alle Eimer überquert, an dem Punkt der Tisch in der Größe angepasst wird. Durch das Kombinieren vielfacher Kuddelmuddel-Funktionen mit vielfachen Zellen pro Eimer kann sehr hohe Raumnutzbarmachung erreicht werden.

Himmel-Und-Hölle-Spiel hashing

Eine andere alternative offen richtende Lösung ist Himmel-Und-Hölle-Spiel hashing, der die Annäherungen des Kuckucks hashing und geradlinige Untersuchung verbindet, noch scheint im Allgemeinen, ihre Beschränkungen zu vermeiden. Insbesondere arbeitet es gut, selbst wenn der Lastfaktor darüber hinaus 0.9 wächst. Für den Algorithmus wird gut angepasst, eine wiederbeträchtliche gleichzeitige Hash-Tabelle durchzuführen.

Das Himmel-Und-Hölle-Spiel hashing Algorithmus arbeitet durch das Definieren einer Nachbarschaft von Eimern in der Nähe vom ursprünglichen hashed Eimer, wo ein gegebener Zugang immer gefunden wird. So wird Suche auf die Zahl von Einträgen in dieser Nachbarschaft beschränkt, die im Grenzfall logarithmisch, durchschnittlich unveränderlich ist, und mit der richtigen Anordnung der Nachbarschaft normalerweise ein geheimes Lager Fräulein verlangt. Wenn man einen Zugang, erste Versuche einfügt, es zu einem Eimer in der Nachbarschaft hinzuzufügen. Jedoch, wenn alle Eimer in dieser Nachbarschaft besetzt werden, überquert der Algorithmus Eimer in der Folge, bis ein offenes Ablagefach (ein freier Eimer) (als in der geradlinigen Untersuchung) gefunden wird. An diesem Punkt, da der leere Eimer außerhalb der Nachbarschaft ist, werden Sachen in einer Folge von Sprüngen wiederholt versetzt. (Das ist dem Kuckuck hashing ähnlich, aber mit dem Unterschied, dass in diesem Fall das leere Ablagefach in die Nachbarschaft statt Sachen bewegt wird, die mit der Hoffnung darauf herausziehen werden, schließlich ein leeres Ablagefach zu finden.) Jeder Sprung bringt das offene Ablagefach, das an der ursprünglichen Nachbarschaft näher ist, ohne das Nachbarschaft-Eigentum von einigen der Eimer entlang dem Weg ungültig zu machen. Schließlich ist das offene Ablagefach in die Nachbarschaft bewegt worden, und der Zugang, der wird einfügt, kann dazu hinzugefügt werden.

Dynamisch in der Größe anzupassen

Um den Lastfaktor unter einer bestimmten Grenze z.B unter 3/4 zu behalten, breiten viele Tabellendurchführungen den Tisch aus, wenn Sachen eingefügt werden. Zum Beispiel in Javas Klasse ist die Verzug-Lastfaktor-Schwelle für die Tabellenvergrößerung 0.75.

Da Eimer gewöhnlich oben auf einer dynamischen Reihe durchgeführt werden und jedes unveränderliche Verhältnis, um größer in der Größe anzupassen, als 1 den Lastfaktor unter der gewünschten Grenze behalten wird, wird die genaue Wahl der Konstante durch denselben Raum-Zeit-Umtausch bezüglich der dynamischen Reihe bestimmt.

In der Größe anzupassen, wird durch ein volles oder zusätzliches Tabellenaufgewärmtes begleitet, wodurch vorhandene Sachen zu neuen Eimer-Positionen kartografisch dargestellt werden.

Das Verhältnis des Gedächtnisses zu beschränken, ist wegen leerer Eimer verschwendet geworden, einige Durchführungen lassen auch die Größe des Tisches — gefolgt von einem Aufgewärmten zusammenschrumpfen — wenn Sachen gelöscht werden. Vom Punkt von Raum-Zeit-Umtauschen ist diese Operation dem deallocation in der dynamischen Reihe ähnlich.

Durch das Kopieren aller Einträge in der Größe anpassend

Eine einheitliche Methode soll automatisch auslösen ganz in der Größe anzupassen, wenn der Lastfaktor eine Schwelle r überschreitet. Dann wird ein neuer größerer Tisch zugeteilt, alle Einträge des alten Tisches werden entfernt und in diesen neuen Tisch eingefügt, und der alte Tisch wird in die freie Lagerungslache zurückgegeben. Symmetrisch, wenn der Lastfaktor unter einer zweiten Schwelle r fällt, werden alle Einträge zu einem neuen kleineren Tisch bewegt.

Wenn die Tabellengröße-Zunahmen oder Abnahmen durch einen festen Prozentsatz bei jeder Vergrößerung, den Gesamtkosten dieser resizings, die über den ganzen Einsatz amortisiert sind, und Operationen löschen, ist noch eine Konstante, die der Zahl von Einträgen n und von der Zahl M von durchgeführten Operationen unabhängig ist.

Denken Sie zum Beispiel einen Tisch, der mit der minimalen möglichen Größe geschaffen wurde und jedes Mal verdoppelt wird, wenn das Lastverhältnis eine Schwelle überschreitet. Wenn M Elemente in diesen Tisch eingefügt wird, ist die Gesamtzahl von Extrawiedereinfügungen, die im ganzen dynamischen resizings des Tisches vorkommen, am grössten Teil der M  1. Mit anderen Worten grob dynamisch in der Größe anzupassen, verdoppelt die Kosten jedes Einsatzes, oder löschen Sie Operation.

Zusätzlich in der Größe anzupassen

Einige Hash-Tabelle-Durchführungen, namentlich in Realtime Systeme, können den Preis nicht bezahlen, die Hash-Tabelle plötzlich zu vergrößern, weil es zeitkritische Operationen unterbrechen kann. Wenn man nicht vermeiden kann dynamisch in der Größe anzupassen, ist eine Lösung durchzuführen allmählich in der Größe anzupassen:

  • Während, in der Größe anzupassen, teilen Sie die neue Hash-Tabelle zu, aber halten Sie den alten Tisch unverändert.
  • In jedem lookup oder löschen Operation, überprüfen beide Tische.
  • Führen Sie Einfügungsoperationen nur im neuen Tisch durch.
  • An jeder Einfügung bewegen auch r Elemente vom alten Tisch bis den neuen Tisch.
  • Wenn alle Elemente vom alten Tisch, deallocate es entfernt werden.

Um sicherzustellen, dass der alte Tisch völlig kopiert wird, vor muss dem neuen Tisch selbst, er vergrößert werden

ist

notwendig, um die Größe des Tisches durch einen Faktor mindestens (r + 1)/r zu vergrößern, während, in der Größe anzupassen.

Monotonische Schlüssel

Wenn es bekannt ist, dass Schlüsselwerte immer (oder Abnahme) monotonically zunehmen werden, dann kann eine Schwankung von konsequentem hashing durch das Halten einer Liste des einzelnen neusten Schlüsselwerts an jeder Hash-Tabelle erreicht werden passen Operation in der Größe an. Auf lookup werden Schlüssel, die in den durch diese Listeneinträge definierten Reihen fallen, zur passenden Kuddelmuddel-Funktion — und tatsächlich Hash-Tabelle geleitet — von denen beide für jede Reihe verschieden sein können. Da es üblich ist, die gesamte Anzahl von Einträgen durch die Verdoppelung anzubauen, wird es nur O (lg (N)) Reihen geben, um zu überprüfen, und die binäre Suchzeit für die Wiederrichtung würde O (lg (lg (N))) sein. Als mit konsequentem hashing versichert diese Annäherung, dass sich das Kuddelmuddel jedes Schlüssels, einmal ausgegeben, nie ändern wird, selbst wenn die Hash-Tabelle später angebaut wird.

Andere Lösungen

Geradliniger hashing ist ein Hash-Tabelle-Algorithmus, der zusätzliche Hash-Tabelle-Vergrößerung erlaubt. Es wird mit einer einzelnen Hash-Tabelle, aber mit zwei möglichen Suchfunktionen durchgeführt.

Eine andere Weise, die Kosten des in der Größe anpassenden Tisches zu vermindern, soll eine Kuddelmuddel-Funktion auf solche Art und Weise wählen, die das Kuddelmuddel von den meisten Werten nicht ändert, wenn der Tisch in der Größe angepasst wird. Diese Annäherung, genannt konsequenten hashing, ist im plattenbasierten und verteilten Kuddelmuddel überwiegend, wo erneute Verhandlung untersagend kostspielig ist.

Leistungsanalyse

Im einfachsten Modell ist die Kuddelmuddel-Funktion völlig unangegeben, und der Tisch passt nicht in der Größe an. Für die bestmögliche Wahl der Kuddelmuddel-Funktion hat ein Tisch der Größe n mit dem offenen Wenden keine Kollisionen und hält bis zu n Elementen mit einem einzelnen Vergleich für erfolgreichen lookup, und ein Tisch der Größe n mit dem Anketten und den k Schlüsseln hat das Minimum max (0, k-n) Kollisionen und O (1 + k/n) Vergleiche für lookup. Für die schlechteste Wahl der Kuddelmuddel-Funktion verursacht jede Einfügung eine Kollision und Hash-Tabellen, die zur geradlinigen Suche, mit Ω (k) amortisierte Vergleiche pro Einfügung und bis zu k Vergleichen für einen erfolgreichen lookup degeneriert sind.

Das Hinzufügen, das zu diesem Modell wieder aufwärmt, ist aufrichtig. Als in einer dynamischen Reihe durch einen Faktor von b geometrisch in der Größe anzupassen, deutet an, dass nur k/b Schlüssel ich oder mehr Male eingefügt werden, so dass die Gesamtzahl von Einfügungen oben durch bk / (b-1) begrenzt wird, der O (k) ist. Durch das Verwenden wieder aufwärmend, um k aufrechtzuerhalten, sind Beide diese Grenzen unveränderlich, wenn wir k/n aufrechterhalten. In kritischen Anwendungen kann universaler hashing verwendet werden; eine Datenstruktur mit besseren Grenzfall-Garantien kann vorzuziehend sein.

Gebrauch

Assoziative Reihe

Hash-Tabellen werden allgemein verwendet, um viele Typen von Tischen im Gedächtnis durchzuführen. Sie werden verwendet, um assoziative Reihe durchzuführen (Reihe, deren Indizes willkürliche Schnuren oder andere komplizierte Gegenstände sind), besonders auf interpretierten Programmiersprachen wie AWK, Perl und PHP.

Wenn die Speicherung eines neuen Artikels in eine Mehrkarte und eine Kuddelmuddel-Kollision vorkommt, versorgt die Mehrkarte unbedingt beide Sachen.

Wenn die Speicherung eines neuen Artikels in eine typische assoziative Reihe und eine Kuddelmuddel-Kollision vorkommt, aber die wirklichen Schlüssel selbst sind verschieden, versorgt die assoziative Reihe ebenfalls beide Sachen. Jedoch, wenn der Schlüssel des neuen Artikels genau den Schlüssel eines alten Artikels vergleicht, löscht die assoziative Reihe normalerweise den alten Artikel und überschreibt ihn mit dem neuen Artikel, so hat jeder Artikel im Tisch einen einzigartigen Schlüssel.

Das Datenbankindexieren

Hash-Tabellen können auch als plattenbasierte Datenstrukturen und Datenbankindizes verwendet werden (solcher als in dbm), obwohl B-Bäume in diesen Anwendungen populärer sind.

Geheime Lager

Hash-Tabellen können verwendet werden, um geheime Lager, Hilfsdatentische durchzuführen, die verwendet werden, um den Zugang zu Daten zu beschleunigen, der in erster Linie in langsameren Medien versorgt wird. In dieser Anwendung können Kuddelmuddel-Kollisionen durch die Verschrottung von einem der zwei kollidierenden Einträge — gewöhnlich das Auslöschen des alten Artikels behandelt werden, der zurzeit im Tisch und Überschreiben davon mit dem neuen Artikel versorgt wird, so hat jeder Artikel im Tisch einen einzigartigen Kuddelmuddel-Wert.

Sätze

Außer der Besserung des Zugangs, der einen gegebenen Schlüssel hat, können viele Hash-Tabelle-Durchführungen auch erzählen, ob solch ein Zugang besteht oder nicht.

Jene Strukturen können deshalb verwendet werden, um eine Satz-Datenstruktur durchzuführen, die bloß registriert, ob ein gegebener Schlüssel einem angegebenen Satz von Schlüsseln gehört. In diesem Fall kann die Struktur durch das Beseitigen aller Teile vereinfacht werden, die mit den Zugang-Werten verbunden sind. Hashing kann verwendet werden, um sowohl statische als auch dynamische Sätze durchzuführen.

Gegenstand-Darstellung

Mehrere dynamische Sprachen, wie Perl, Pythonschlange, JavaScript, und Ruby, verwenden Hash-Tabellen, um Gegenstände durchzuführen. In dieser Darstellung sind die Schlüssel die Namen der Mitglieder und Methoden des Gegenstands, und die Werte sind Zeigestöcke dem entsprechenden Mitglied oder der Methode.

Einzigartige Datendarstellung

Hash-Tabellen können durch einige Programme verwendet werden, um zu vermeiden, vielfache Charakter-Schnuren mit demselben Inhalt zu schaffen. Zu diesem Zweck werden alle Schnuren im Gebrauch durch das Programm in einer einzelnen Hash-Tabelle versorgt, die überprüft wird, wann auch immer eine neue Schnur geschaffen werden muss. Diese Technik wurde in Lispeln-Dolmetschern unter dem Namenkuddelmuddel consing eingeführt, und kann mit vielen anderen Arten von Daten (Ausdruck-Bäume in einem symbolischen Algebra-System, Aufzeichnungen in einer Datenbank, Dateien in einem Dateisystem, binären Entscheidungsdiagrammen, usw.) verwendet werden

Das Schnur-Internieren

Durchführungen

Auf Programmiersprachen

Viele Programmiersprachen stellen Hash-Tabelle-Funktionalität entweder als eingebaute assoziative Reihe oder als Standardbibliotheksmodule zur Verfügung. In C ++ 11, zum Beispiel, stellt die Klasse Hash-Tabellen für Schlüssel und Werte des willkürlichen Typs zur Verfügung.

In PHP 5 Zend verwendet 2 Motor eine der Kuddelmuddel-Funktionen von Daniel J. Bernstein, die Kuddelmuddel-Werte zu erzeugen, die im Handhaben des mappings von in einer Hash-Tabelle versorgten Datenzeigestöcken verwendet sind. Im PHP Quellcode wird es als (Daniel J. Bernstein, Zeiten 33 mit der Hinzufügung) etikettiert.

Die eingebaute Hash-Tabelle-Durchführung der Pythonschlange, in der Form des Typs, sowie des Kuddelmuddel-Typs von Perl (%) werden hoch optimiert, weil sie innerlich verwendet werden, um namespaces durchzuführen.

Im.NET Fachwerk wird die Unterstützung für Hash-Tabellen über die spezifischen und allgemeinen Klassen zur Verfügung gestellt, die Schlüsselwert-Paare und die allgemeine Klasse versorgen, die nur Werte versorgt.

Unabhängige Pakete

  • SparseHash (früher Google SparseHash) Eine äußerst speichereffiziente hash_map Durchführung, mit nur 2 Bit/Zugäng oben. Die Bibliothek von SparseHash hat mehrere C ++ Kuddelmuddel-Karte-Durchführungen mit verschiedenen Leistungseigenschaften einschließlich derjenigen, die für den Speichergebrauch und einen anderen optimiert, der für die Geschwindigkeit optimiert.
  • SunriseDD Eine offene Quelle C Bibliothek für die Hash-Tabelle-Lagerung von willkürlichen Daten protestiert mit lookups ohne Schlösser, dem eingebauten Bezugszählen und der versicherten Ordnungswiederholung. Die Bibliothek kann an Zählen-Systemen des externen Verweises teilnehmen oder sein eigenes eingebautes Bezugszählen verwenden. Es kommt mit einer Vielfalt des Kuddelmuddels fungiert und erlaubt den Gebrauch gelieferter Kuddelmuddel-Funktionen der Durchlaufzeit über den Rückrufaktionsmechanismus. Quellcode wird gut dokumentiert.
  • uthash ist Das eine gebrauchsfreundliche Hash-Tabelle für C Strukturen.

Geschichte

Die Idee von hashing ist unabhängig in verschiedenen Plätzen entstanden. Im Januar 1953 hat H. P. Luhn einen inneren Vermerk von IBM geschrieben, der hashing mit dem Anketten verwendet hat. G. N. Amdahl, E. M. Boehme, N. Rochester und Arthur Samuel haben ein Programm mit hashing in ungefähr derselben Zeit durchgeführt. Das offene Wenden mit der geradlinigen Untersuchung (das relativ erste Treten) wird Amdahl kreditiert, aber Ershov (in Russland) hatte dieselbe Idee.

Siehe auch

  • Schnur von Rabin-Karp sucht Algorithmus
  • Stabiler hashing
  • Konsequenter hashing
  • Ausdehnbarer hashing
  • Faules Auswischen
  • Pearson hashing

Zusammenhängende Datenstrukturen

Es gibt mehrere Datenstrukturen, die Kuddelmuddel-Funktionen verwenden, aber spezielle Fälle von Hash-Tabellen nicht in Betracht gezogen werden können:

  • Blüte-Filter, eine Struktur, die eine Umgeben-Annäherung eines Satzes durchführt, Einfügungen, aber nicht Auswischen erlaubend.
  • Verteilte Hash-Tabelle (DHT), ein elastischer dynamischer Tisch hat sich über mehrere Knoten eines Netzes ausgebreitet.
  • Kuddelmuddel-Reihe hat trie kartografisch dargestellt, eine trie Struktur, die der Reihe ähnlich ist, hat trie kartografisch dargestellt, aber wo jeder Schlüssel hashed zuerst ist.

Weiterführende Literatur

Links


Menschenrechte / Hallo Weltprogramm
Impressum & Datenschutz