Warum ist std :: map als implementiert rot-schwarz - Baum ?
Es gibt mehrere ausgeglichene binäre Suchbäume (BSTs) da draußen. Was waren Design Trade-offs in einen rot-schwarz - Baum auswählen?
Warum ist std :: map als implementiert rot-schwarz - Baum ?
Es gibt mehrere ausgeglichene binäre Suchbäume (BSTs) da draußen. Was waren Design Trade-offs in einen rot-schwarz - Baum auswählen?
Wahrscheinlich sind die beiden häufigsten Baum Selbstausgleichsalgorithmen sind Rot-Schwarz Bäume und AVL - Bäume . Zum Ausgleich des Baumes nach einem Update Einfügen / beide Algorithmen , um die Vorstellung von Rotationen verwenden , in denen die Knoten des Baumes gedreht werden , um die Neugewichtung durchzuführen.
Während sowohl die Insert - Algorithmen / Löschoperationen sind O (log n), im Falle von Rot-Schwarz - Baum Neugewichtung Rotation ist ein O (1) Betrieb während mit AVL dies ist ein O (n log) Betrieb, so dass die rot-Schwarz - Baum effizienter in diesem Aspekt der Neugewichtung Stufe und einer der möglichen Gründe dafür , dass es häufiger verwendet wird.
Rot-Schwarz Bäume sind in den meisten Sammlung Bibliotheken, darunter die Angebote von Java und Microsoft .NET Framework verwendet.
Es ist nur die Wahl Ihrer Umsetzung - sie als eine funktionierende Baum umgesetzt werden könnten. Die verschiedenen Möglichkeiten sind vergleichbar mit kleinen Unterschieden. Deshalb ist jeder so gut wie jeder andere.
AVL-Bäume haben eine maximale Höhe von 1.44logn, während RB Bäume maximal 2logn haben. ein Element in einem AVL Einsetzen kann eine Neuverteilung bei einem Punkt in der Baumstruktur impliziert. Die rebalancing beendet die Insertion. Nach dem Einsetzen eines neuen Blatt hat die Vorfahren des Blattes Aktualisierung an die Wurzel getan werden, oder bis zu einem Punkt, wo die beiden Unterstrukturen von gleicher Tiefe sind. Die Wahrscheinlichkeit von Knoten k zu aktualisieren ist, die 1/3 ^ k. Rebalancing ist O (1). Entfernen ein Elements kann mehr als einen ausgleich implizieren (bis zur Hälfte der Tiefe des Baumes).
RB-Bäume sind B-Bäume der Ordnung 4 als binäre Suchbäume dargestellt. Ein 4-Knoten in den B-Baum-Ergebnissen in zwei Ebenen in der äquivalenten BST. Im schlimmsten Fall sind alle Knoten des Baums sind 2-Knoten, mit nur einer Kette von 3-Knoten bis zu einem Blatt. Das Blatt wird von der Wurzel in einem Abstand von 2logn sein.
Ablaufend von der Wurzel bis zur Einfügemarke, hat ein 4-Knoten in 2-Knoten zu ändern, jede Einfügung, um sicherzustellen, wird ein Blatt nicht sättigen. Kommen wir zurück von der Insertion, all diese Knoten müssen analysiert werden, um sicherzustellen, dass sie richtig 4-Knoten repräsentieren. Dies kann auch hinunter in den Baum durchgeführt werden. Die Gesamtkosten werden die gleichen sein. Es gibt kein freies Mittagessen! ein Element aus dem Baum zu entfernen, ist in der gleichen Größenordnung.
Alle diese Bäume erfordern, dass die Knoten tragen Informationen über Größe, Gewicht, Farbe, etc. Nur Splay Bäume sind frei von solchen zusätzlichen Informationen. Aber die meisten Menschen haben Angst vor Splay Bäume wegen der ramdomness ihrer Struktur!
Schließlich Bäume können auch Gewichtsinformationen in den Knoten führen, Gewichtsausgleich ermöglicht. Verschiedene Schemata können angewendet werden. Man sollte Neuverteilung wenn ein Teilbaum mehr als 3 mal die Anzahl der Elemente des anderen Teilbaum enthält. Rebalancing wird wieder entweder throuh Einzel- oder Doppeldrehung erfolgt. Das bedeutet, eine Worst-Case von 2.4logn. Man kann mit 2 mal weg statt 3, ein viel besseres Verhältnis, aber es kann bedeuten, etwas weniger thant 1% der Teilbäume verlassen unausgewogen hier und da. Tricky!
Welche Art von Baum ist die beste? AVL sicher. Sie sind am einfachsten zu Code und haben ihre schlimmste Höhe am nächsten logn. Für einen Baum von Elementen 1000000 wird eine AVL höchstens der Höhe beträgt 29, eine RB 40 und ein Gewicht 36 oder 50 je nach dem Verhältnis ausgewogen.
Es gibt eine Menge von anderen Variablen: Zufälligkeit, das Verhältnis der hinzufügt, löscht, Durchsuchung, usw.
Es hängt wirklich von der Nutzung. AVL-Baum hat in der Regel mehr Drehungen Rebalancing. Also, wenn Ihre Anwendung nicht über zu viele Einfügen und Löschen-Operationen, aber Gewichte stark auf Suche, dann wahrscheinlich AVL-Baum ist eine gute Wahl.
std::map verwendet Rot-Schwarz-Baum, wie es einen vernünftigen Kompromiss zwischen der Geschwindigkeit der Knoten Einfügen / Löschen und der Suche wird.
Aktualisieren 2017.06.14: webbertiger bearbeiten ihre Antwort, nachdem ich kommentiert. Ich sollte darauf hinweisen, dass die Antwort ist jetzt viel besser in meinen Augen. Aber ich behielt meine Antwort nur als zusätzliche Informationen ...
Aufgrund der Tatsache, dass ich denke, erste Antwort falsch ist (Korrektur: nicht beide mehr) und der dritte eine falsche Behauptung hat. Ich glaube, ich hatte Dinge zu klären ...
Der 2 beliebtestene Baum ist AVL und Rot Schwarz (RB). Der Hauptunterschied liegt in der Verwendung:
Der Hauptunterschied von der Färbung kommen. Sie haben noch weniger wieder ins Gleichgewicht Aktion in RB Baum als AVL, weil die Färbung Sie manchmal ermöglichen, wieder ins Gleichgewicht Aktion überspringen oder zu verkürzen, die ein relativ hallo Kosten haben. Wegen der Färbung, auch RB Baum höhere Ebene von Knoten haben, weil es rot Knoten zwischen schwarzen annehmen könnte (mit den Möglichkeiten von ~ 2x mehr Ebenen) zu machen suchen (lesen) ein wenig weniger effizient ... aber da es sich um eine konstante (2x), ist es in O (log n) bleiben.
Wenn Sie die Performance-Einbußen für eine Änderung eines Baumes (significative) VS die Leistungseinbußen der Konsultation eines Baumes (fast unbedeutend) betrachten, werden sie natürlich RB über AVL für einen allgemeinen Fall zu bevorzugen.
Die bisherigen Antworten Adresse nur Baum Alternativen und rot schwarz bleibt wohl nur aus historischen Gründen.
Warum nicht eine Hash-Tabelle?
In einem Baum erfordert eine Art nur partielle Ordnung (<Vergleich) als Schlüssel in der Karte verwendet werden. Jedoch Hash-Tabellen erfordern, dass jeder Schlüsseltyp eine Hash-Funktion definiert ist. diese Art Anforderungen auf ein Minimum zu halten, ist sehr wichtig für die generische Programmierung.
eine gute Hash-Tabelle Gestaltung erfordert genaue Kenntnis des Kontexts es, die sie verwendet werden sollen. Sollte es offen Adressierung oder verknüpft Verkettungs verwenden? Welche Ebene der Last soll es vor dem Ändern der Größe annehmen? Sollte es eine teure Hash verwenden, die Kollisionen vermeidet, oder eine, die rau und schnell ist?
(C ++ 11 hat mit Hash - Tabellen hinzufügen unordered_map. Sie können von der siehe Dokumentation es erfordert Richtlinien Einstellung viele dieser Optionen zu konfigurieren.)
Da die STL nicht voraussehen kann, welche die beste Wahl für Ihre Anwendung ist, muss der Standard flexibler sein. Bäume „einfach funktionieren“ und skalieren schön.
Was ist mit anderen Bäumen?
Red Black tree Angebot schnelles Nachschlagen und balancieren sich selbst im Gegensatz zu BSTs. Ein anderer Benutzer darauf hingewiesen, ihre Vorteile gegenüber dem Selbst-Balancing AVL-Baum.
Alexander Stepanov (Der Schöpfer des STL) sagte , dass er einen B * -Baum anstelle eines Rot-Schwarz - Baum verwenden würde , wenn er schrieb std::mapwieder. Dies liegt daran , die Knoten eine beliebige Anzahl von Elementen speichern kann zusammenhängend , die freundlicher für moderne Speicher - Caches ist.
Eine der größten Veränderungen seit damals hat sich das Wachstum von Caches gewesen. Cache-Misses sind sehr teuer, so Referenzlokalität ist viel wichtiger, jetzt. Node-basierte Datenstrukturen, die eine niedrige Referenzlokalität haben, machen viel weniger Sinn. Wenn ich STL heute entwarfen, würde ich einen anderen Satz von Containern haben. Zum Beispiel ist ein In-Memory-B * -Baum eine weit bessere Wahl als ein rot-schwarz-Baum für einen assoziativen Container implementieren. - Alexander Stepanov
Sie können mehr lesen hier
Ist Rot-Schwarz-Baum oder B * immer die beste?
Bei anderen Gelegenheiten Alex hat erklärt , dass std::vectorfast immer die beste Liste Container aus ähnlichen Gründen sind. Es macht selten Sinn zu verwenden std::listoder std::dequeauch für jene Situationen , die wir in der Schule (wie das Entfernen eines Elements aus der Mitte der Liste) unterrichtet wurden. std::vectorso schnell ist , dass es diese Strukturen für alles , aber große n schlägt.
Die gleiche Argumentation Anwendung , wenn Sie nur eine kleine Anzahl von Elementen haben (Hunderte?) Eine mit std::vectorund linearen Suche kann effizienter als der Baum Umsetzung sein std::map. Je nach Häufigkeit des Einsetzens, sortierte eine std::vectorKombination mit std::binary_searchkann die schnellste Wahl sein.