Wenn ich also zwischen einer Hash-Tabelle oder einem Präfixbaum wählen muss, was sind die Unterscheidungsfaktoren, die mich dazu bringen würden, einen über den anderen zu wählen? Aus meiner naiven Sicht scheint es, als hätte die Verwendung eines Tries einen zusätzlichen Aufwand, da er nicht als Array gespeichert ist, sondern in Bezug auf die Laufzeit (vorausgesetzt, der längste Schlüssel ist das längste englische Wort) im Wesentlichen O sein kann (1) (in Bezug auf die Obergrenze). Vielleicht ist das längste englische Wort 50 Zeichen?
Hash-Tabellen werden sofort nachgeschlagen, sobald Sie den Index erhalten haben . Das Drücken der Taste, um den Index zu erhalten, scheint jedoch leicht fast 50 Schritte zu dauern.
Kann mir jemand eine erfahrenere Perspektive dazu geben? Vielen Dank!
quelle
00110010
könnte das Eingabebyte sein, aber Sie möchten die Übereinstimmung einschließen, die00111010
nur ein Bit entfernt ist.Antworten:
Vorteile von Versuchen:
Die Grundlagen:
Neue Operationen:
Vorteile der verknüpften Struktur:
Vorteile von Hashtabellen:
quelle
Es hängt alles davon ab, welches Problem Sie lösen möchten. Wenn Sie nur Einfügungen und Suchvorgänge ausführen müssen, verwenden Sie eine Hash-Tabelle. Wenn Sie komplexere Probleme wie Präfix-bezogene Abfragen lösen müssen, ist ein Versuch möglicherweise die bessere Lösung.
quelle
Jeder kennt die Hash-Tabelle und ihre Verwendung, aber es ist nicht gerade eine konstante Nachschlagezeit. Sie hängt davon ab, wie groß die Hash-Tabelle ist und wie komplex die Hash-Funktion ist.
Das Erstellen großer Hash-Tabellen für eine effiziente Suche ist in den meisten industriellen Szenarien, in denen selbst eine geringe Latenz / Skalierbarkeit von Bedeutung ist (z. B. Hochfrequenzhandel), keine elegante Lösung. Sie müssen sich um die Datenstrukturen kümmern, die für den Speicherplatz optimiert werden sollen, den sie auch im Speicher beanspruchen, um den Cache-Fehler zu reduzieren.
Ein sehr gutes Beispiel, bei dem die Anforderungen besser erfüllt werden, ist die Messaging-Middleware. Sie haben eine Million Abonnenten und Herausgeber von Nachrichten in verschiedenen Kategorien (in JMS-Begriffen - Themen oder Austausch). Wenn Sie in solchen Fällen Nachrichten nach Themen herausfiltern möchten (die eigentlich Zeichenfolgen sind), möchten Sie definitiv keine Hash-Tabelle erstellen für die Millionen Abonnements mit Millionen Themen. Ein besserer Ansatz besteht darin, die Themen in trie zu speichern. Wenn die Filterung auf der Grundlage der Themenübereinstimmung erfolgt, ist ihre Komplexität unabhängig von der Anzahl der Themen / Abonnements / Herausgeber (hängt nur von der Länge der Zeichenfolge ab). Ich mag es, weil Sie mit dieser Datenstruktur kreativ sein können, um den Platzbedarf zu optimieren und somit einen geringeren Cache-Miss zu haben.
quelle
Verwenden Sie einen Baum:
quelle
Es gibt etwas, das ich nicht ausdrücklich erwähnt habe und das ich für wichtig halte. Sowohl Hash-Tabellen als auch Versuche verschiedener Art haben normalerweise
O(k)
Operationen, wobeik
die Länge der Zeichenfolge in Bits (oder äquivalent in Zeichen) angegeben ist.Dies setzt voraus, dass Sie eine gute Hash-Funktion haben. Wenn Sie nicht möchten, dass "Farm" und "Farm Animals" denselben Wert haben, muss die Hash-Funktion alle Bits des Schlüssels verwenden. Daher sollte das Hashing von "Farm Animals" etwa doppelt so lange dauern wie "farm" (es sei denn, Sie befinden sich in einem rollierenden Hash-Szenario, aber es gibt auch ähnliche betriebssparende Szenarien mit Versuchen). Und mit einem Vanille-Versuch ist klar, warum das Einfügen von "Nutztieren" etwa doppelt so lange dauert wie das Einfügen von "Nutztieren". Auf lange Sicht gilt dies auch für komprimierte Versuche.
quelle
Das Einfügen und Nachschlagen eines Versuchs erfolgt linear mit der Länge der Eingabezeichenfolge O (s).
Ein Hash gibt Ihnen ein O (1) zum Nachschlagen und Einfügen, aber zuerst müssen Sie den Hash basierend auf der Eingabezeichenfolge berechnen, die wiederum O (s) ist.
Schlussfolgerung: Die asymptotische Zeitkomplexität ist in beiden Fällen linear.
Der Trie hat aus Datenperspektive etwas mehr Overhead, aber Sie können einen komprimierten Trie auswählen, der Sie mehr oder weniger mit der Hash-Tabelle in Verbindung bringt.
Um die Krawatte zu lösen, stellen Sie sich folgende Frage: Muss ich nur nach vollständigen Wörtern suchen? Oder muss ich alle Wörter zurückgeben, die einem Präfix entsprechen? (Wie in einem prädiktiven Texteingabesystem). Für den ersten Fall gehen Sie für einen Hash. Es ist einfacher und sauberer Code. Einfacher zu testen und zu warten. Für einen ausgefeilteren Anwendungsfall, bei dem Präfixe oder Sufixe eine Rolle spielen, versuchen Sie es.
Und wenn Sie es nur zum Spaß tun, würde die Implementierung eines Tries einen Sonntagnachmittag sinnvoll nutzen.
quelle
Die HashTable- Implementierung ist im Vergleich zur grundlegenden Trie- Implementierung platzsparend . Bei Zeichenfolgen ist jedoch in den meisten praktischen Anwendungen eine Bestellung erforderlich. Aber HashTable stört die lexografische Reihenfolge völlig. Wenn Ihre Anwendung jetzt Operationen basierend auf der lexografischen Reihenfolge ausführt (z. B. Teilsuche, alle Zeichenfolgen mit angegebenem Präfix, alle Wörter in sortierter Reihenfolge), sollten Sie Versuche verwenden. Nur für die Suche sollte HashTable verwendet werden (da dies wohl eine minimale Suchzeit bietet).
PS: Anders als diese, Ternary Suchbäume (TSTs) wäre eine ausgezeichnete Wahl. Die Suchzeit ist länger als bei HashTable, bei allen anderen Vorgängen jedoch zeiteffizient. Außerdem ist es platzsparender als Versuche.
quelle
Einige (normalerweise eingebettete Echtzeitanwendungen) erfordern, dass die Verarbeitungszeit unabhängig von den Daten ist. In diesem Fall kann eine Hash-Tabelle eine bekannte Ausführungszeit garantieren, während ein Versuch basierend auf den Daten variiert.
quelle