Wann sind Binärbäume in realen Anwendungen besser als Hashtabellen?


7

Ich arbeite derzeit an meinen Datenstrukturen und grundlegenden Algorithmen, ein Teil davon ist der Binärbaum. Ich verstehe die Algorithmen und wie man einen binären Suchbaum und so implementiert. Ich mache es so schlau, dass wir in O (log n) Zeit nachschlagen können.

Es fällt mir jedoch schwer, ein Beispiel dafür zu finden, wann ich einen Binärbaum verwenden würde, bei dem Hash-Tabellen nicht den gleichen / besseren Job machen würden. Ich habe ein bisschen gesucht und festgestellt, dass es für 3D-Grafiken verwendet wird, etwas darüber, welche Elemente angezeigt werden sollen, aber es fällt mir schwer, dies zu tun.

Kann mir jemand ein Beispiel geben, wo es besser wäre, einen Binärbaum über einer Hash-Tabelle zu verwenden?

Antworten:


14

Hash-Tabellen können Ihnen nur sagen, ob ein Element vorhanden ist oder nicht.

Hier sind einige Dinge, die Sie mit einem Binärbaum tun können, die Sie mit einer Hash-Tabelle nicht tun können.

  • sortierte Durchquerung des Baumes
  • finde das nächstgelegene Element
  • Finden Sie alle Elemente, die kleiner oder größer als ein bestimmter Wert sind

In diesem Wikipedia-Artikel über Kd-Bäume finden Sie ein Beispiel für eine reale Datenstruktur, die die besonderen Eigenschaften von Binärbäumen nutzt. http://en.wikipedia.org/wiki/K-d_tree


1
Haben Sie auch sublineare Laufzeitgarantien im ungünstigsten Fall.
Raphael

11

Eine Anwendungsdomäne, in der Binärbäume besser oder leichter anpassbar sind als bestimmte Alternativen, sind persistente Datenstrukturen (die häufig in der (rein) funktionalen Programmierung verwendet werden).

Eine persistente Datenstruktur ist eine Datenstruktur, die die vorherige Version von sich selbst beibehält, wenn sie geändert wird. (Datenstrukturen, die diese Eigenschaft nicht haben, werden als kurzlebig bezeichnet .) Ein Vorteil dieser Art von Datenstruktur besteht darin, dass Teile der Datenstruktur gemeinsam genutzt werden können. Da sich die Struktur selbst garantiert nicht ändert, ist es sicher, sie gemeinsam zu nutzen frei zwischen anderen Datenstrukturen und sogar Threads, ohne sich Sorgen machen zu müssen, dass sich diese ändern. Ein weiterer subjektiver Vorteil besteht darin, dass diese Datenstrukturen leichter zu verstehen sind.

Konzeptionell könnten Sie einen unveränderlichen Datentyp haben, der eine Liste von Zahlen ist, z. L.1={3,4,5}}. Dann könnten Sie einen neuen Wert einführen, der zwei Zahlen am Anfang dieser Liste hinzufügt:L.2=cÖns(1,cÖns(2,L.1))={1,2,3,4,5}}. Was passierte mitL.1? Nichts -L.1={3,4,5}}, immer noch. HatL.2Kopieren Sie diese drei Elemente und fügen Sie sie in eine eigene Liste ein. Im Idealfall nicht - die Werte in der ListeL.1 gehört L.2, ebenfalls:

1,2,3,4,5L.1L.2

Es gibt Datenstrukturen, die sich besser für die Implementierung persistenter Listen wie der oben genannten eignen. Ebenso eignen sich Binärbäume besser für die Implementierung persistenter Datenstrukturen mit bestimmten Eigenschaften als andere Datenstrukturen oder Strategien. Die im Beispiel gezeigte strukturelle Freigabe mit den beiden Listen überträgt sich auf Binärbäume. Sie können sich vorstellen, dass mehrere Versionen eines Baums Teilbäume gemeinsam nutzen können, die sie gemeinsam haben.

Wie gesagt, einige Datenstrukturen lassen sich leichter ändern, um dauerhaft zu sein. Sie erwähnen die Hash-Tabelle, bei der es sich normalerweise (wenn nicht sogar unbedingt) um eine kurzlebige Datenstruktur handelt. Es scheint weniger offensichtlich, wie man eine gemeinsame Implementierungsstrategie anpassen kann, damit eine Hash-Tabelle dauerhaft ist. Beachten Sie, dass eine Hash-Tabelle häufig mit einem Array implementiert wird (insbesondere Arrays, die als kontinuierlicher Teil des Speichers implementiert sind). Arrays sind nett, da sie zufälligen Zugriff auf Elemente bieten. Dies ist eine wichtige Eigenschaft, die Sie idealerweise haben möchtenÖ(1)durchschnittlicher Zugriff auf Elemente in der Hash-Tabelle. Aber Arrays sind nicht so schön, wenn es darum geht, persistente Datenstrukturen aufzubauen. Das Wesentliche dabei ist, dass Sie zwar einen unveränderlichen Array-Datentyp erstellen können, jedoch aufgrund der Art der Arrays das Risiko besteht, viel kopieren zu müssen. Wenn der oben genannte Listentyp mit Arrays implementiert würde, müssten Sie einen erstellen ganz neues Array mit fünf Elementen, anstatt einen Teil davon zu teilen. Und was ist, wenn Sie etwas in der Mitte des Arrays ändern möchten? Die naheliegendste - und scheinbar unvermeidliche - Antwort ist wiederum das Kopieren .

Persistente Datenstrukturen vermeiden im Allgemeinen nicht das Kopieren. Bestimmte Datenstrukturen machen das Kopieren jedoch weniger häufig. Dies ist eine wünschenswerte Eigenschaft, wenn Sie verlangen, dass eine Datenstruktur unveränderlich sein muss.


Die Probleme mit persistenten Arrays, die Sie in Ihrem vorletzten Absatz erwähnen, sind wahrscheinlich der Grund, warum Clojure seine Vektoren mit wahlfreiem Zugriff mit großen, flachen Bäumen implementiert, anstatt Java-Arrays zu verwenden. Sie habenÖ(Log32(n)) Zugriffszeit statt Ö(1), aber sie können leicht Struktur teilen.
Tsleyson

1
Ich habe einmal rein funktionierende rot-schwarze Bäume in einem Java-Programm verwendet, um eine große Anzahl ähnlicher Bitsets zu speichern, was die Speichernutzung drastisch reduzierte und es mir ermöglichte, ihren Jaccard-Ähnlichkeitskoeffizienten schnell zu berechnen. Solche Bäume können auch effizient auf (In-) Gleichheit verglichen werden, indem ein Hash beibehalten wird - z. B. indem jeder Knoten das XOR von Hashes seiner Zweige speichert; Dies ist trivial, um unter Rotationen zu halten.
JKFF

4

Ein Binärbaum hat viele Anwendungen, insbesondere wenn wir alle Binärbäume und nicht nur binäre Suchbäume einschließen. Heaps werden als Binärbäume implementiert, wobei das oberste Element entweder ein Min- oder ein Maximalwert aller Elemente ist. Dies ist sehr nützlich für ein Szenario, in dem eine Prioritätswarteschlange erforderlich ist.

Hashmaps sind sehr effizient in einer festgelegten Art von Operation, bei der lediglich die Existenz eines Elements überprüft wird. Sie sind jedoch schwächer, wenn es darum geht, nicht existierende Überprüfungsvorgänge für geordnete oder sortierte Daten durchzuführen. Während es mit der Optimierung der Hash-Algorithmen möglich wäre, scheinen Binärbäume den Begriff der partiellen Schlüsselsuche besser zu unterstützen. Zum Beispiel könnte man versuchen, einen binären Baum von Strings zu verwenden, um zu beantworten, welche Wörter mit "an" beginnen. Zugegeben, ein Versuch wäre eine bessere Datenstruktur für diese Art von Szenario.

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.