Warum stellt die C ++ STL keine "Baum" -Container bereit?

373

Warum bietet die C ++ STL keine "Baum" -Container und was ist stattdessen die beste Verwendung?

Ich möchte eine Hierarchie von Objekten als Baum speichern, anstatt einen Baum als Leistungssteigerung zu verwenden ...

Roddy
quelle
7
Ich brauche einen Baum, um eine Darstellung einer Hierarchie zu speichern.
Roddy
20
Ich bin mit dem Typen zusammen, der die "richtigen" Antworten abgelehnt hat, was zu sein scheint; "Bäume sind nutzlos". Es gibt wichtige, wenn obskure Verwendungen von Bäumen.
Joe Soul-Bringer
Ich denke, der Grund ist trivial - noch hat ihn niemand in der Standardbibliothek implementiert. Es ist wie Standardbibliothek hatte keine std::unordered_mapund std::unordered_setbis vor kurzem. Und vorher gab es überhaupt keine STL-Container in der Standardbibliothek.
Doc
1
Meine Gedanken (nachdem ich den relevanten Standard noch nie gelesen habe, daher ist dies ein Kommentar, keine Antwort) sind, dass sich die STL nicht um bestimmte Datenstrukturen kümmert, sondern um Spezifikationen hinsichtlich der Komplexität und der unterstützten Operationen. Die zugrunde liegende Struktur kann daher zwischen Implementierungen und / oder Zielarchitekturen variieren, sofern sie den Spezifikationen entspricht. Ich bin mir ziemlich sicher std::mapund std::setwerde in jeder Implementierung einen Baum verwenden, aber sie müssen nicht, wenn eine Nicht-Baumstruktur auch den Spezifikationen entspricht.
Mark K Cowan

Antworten:

182

Es gibt zwei Gründe, warum Sie einen Baum verwenden möchten:

Sie möchten das Problem mithilfe einer baumartigen Struktur spiegeln:
Dafür haben wir eine Boost-Graph-Bibliothek

Oder Sie möchten einen Container mit baumartigen Zugriffseigenschaften. Dafür haben wir

Grundsätzlich sind die Eigenschaften dieser beiden Container so, dass sie praktisch mithilfe von Bäumen implementiert werden müssen (obwohl dies eigentlich keine Anforderung ist).

Siehe auch diese Frage: C-Baum-Implementierung

Martin York
quelle
64
Es gibt viele, viele Gründe, einen Baum zu verwenden, auch wenn diese am häufigsten vorkommen. Am häufigsten! Gleich alle.
Joe Soul-Bringer
3
Ein dritter Hauptgrund, einen Baum zu wollen, ist eine immer sortierte Liste mit schnellem Einfügen / Entfernen, aber dafür gibt es std: multiset.
VoidStar
1
@Durga: Nicht sicher, wie die Tiefe relevant ist, wenn Sie die Karte als sortierten Container verwenden. Map garantiert das Einfügen / Löschen / Nachschlagen von Protokollen (n) (und enthält Elemente in sortierter Reihenfolge). Dies ist alles, wofür die Karte verwendet wird und (normalerweise) als rot / schwarzer Baum implementiert wird. Ein rot / schwarzer Baum sorgt dafür, dass der Baum ausgeglichen ist. Die Tiefe des Baums hängt also direkt mit der Anzahl der Elemente im Baum zusammen.
Martin York
14
Ich bin mit dieser Antwort nicht einverstanden, sowohl 2008 als auch jetzt. Die Standardbibliothek "hat" keinen Boost, und die Verfügbarkeit von Boost sollte (und war) kein Grund sein, ihn nicht in den Standard aufzunehmen. Darüber hinaus ist die BGL allgemein und involviert genug, um von ihr unabhängige spezialisierte Baumklassen zu verdienen. Auch die Tatsache, dass std :: map und std :: set einen Baum erfordern, ist, IMO, ein weiteres Argument für ein stl::red_black_treeusw. Schließlich sind die std::mapund std::setBäume ausgeglichen, und std::treemöglicherweise nicht.
Einpoklum
1
@einpoklum: "Die Verfügbarkeit von etwas in Boost sollte kein Grund sein, es nicht in den Standard aufzunehmen" - da einer der Zwecke von Boost darin besteht, vor der Aufnahme in den Standard als Testgelände für nützliche Bibliotheken zu dienen, kann ich nur sag "absolut!".
Martin Bonner unterstützt Monica
94

Wahrscheinlich aus dem gleichen Grund, dass kein Baumcontainer in Boost ist. Es gibt viele Möglichkeiten, einen solchen Container zu implementieren, und es gibt keine gute Möglichkeit, alle zufrieden zu stellen, die ihn verwenden würden.

Einige zu berücksichtigende Punkte:

  • Ist die Anzahl der untergeordneten Elemente für einen Knoten fest oder variabel?
  • Wie viel Overhead pro Knoten? - Benötigen Sie übergeordnete Zeiger, Geschwisterzeiger usw.
  • Welche Algorithmen sind bereitzustellen? - verschiedene Iteratoren, Suchalgorithmen usw.

Am Ende besteht das Problem darin, dass ein Baumcontainer, der für alle nützlich genug wäre, zu schwer wäre, um die meisten Benutzer zufrieden zu stellen. Wenn Sie nach etwas Mächtigem suchen, ist Boost Graph Library im Wesentlichen eine Obermenge dessen, wofür eine Baumbibliothek verwendet werden könnte.

Hier sind einige andere generische Baumimplementierungen:

Greg Rogers
quelle
5
"... kein guter Weg, um alle zufrieden zu stellen ..." Da stl :: map, stl :: multimap und stl :: set auf stls rb_tree basieren, sollte es genauso viele Fälle erfüllen wie diese Grundtypen .
Catskul
44
Da es keine Möglichkeit gibt, die untergeordneten Elemente eines Knotens von a abzurufen std::map, würde ich diese Baumcontainer nicht aufrufen. Dies sind assoziative Container, die üblicherweise als Bäume implementiert werden. Großer Unterschied.
Mooing Duck
2
Ich stimme Mooing Duck zu. Wie würden Sie eine umfassende erste Suche auf einer std :: map implementieren? Es wird furchtbar teuer
Marco A.
1
Ich habe angefangen, Kasper Peeters 'tree.hh zu verwenden, aber nachdem ich die Lizenzierung für GPLv3 oder eine andere GPL-Version überprüft habe, würde dies unsere kommerzielle Software kontaminieren. Ich würde empfehlen, sich den Baumbaum im Kommentar von @hplbsh anzusehen, wenn Sie eine Struktur für kommerzielle Zwecke benötigen.
Jake88
3
Die sortenspezifischen Anforderungen an Bäume sind ein Argument dafür, verschiedene Baumarten zu haben, überhaupt keine.
André
50

Die STL-Philosophie lautet, dass Sie einen Container basierend auf Garantien und nicht basierend auf der Implementierung des Containers auswählen. Zum Beispiel kann Ihre Wahl des Containers auf der Notwendigkeit einer schnellen Suche beruhen. Bei allem, was Sie interessiert, kann der Container als unidirektionale Liste implementiert werden - solange die Suche sehr schnell ist, wären Sie glücklich. Das liegt daran, dass Sie die Interna sowieso nicht berühren, sondern Iteratoren oder Elementfunktionen für den Zugriff verwenden. Ihr Code ist nicht daran gebunden, wie der Container implementiert wird, sondern daran, wie schnell er ist oder ob er eine feste und definierte Reihenfolge hat oder ob er platzsparend ist und so weiter.

wilhelmtell
quelle
12
Ich glaube nicht, dass er über Containerimplementierungen spricht, er spricht über einen tatsächlichen Baumcontainer selbst.
Mooing Duck
3
@MooingDuck Ich denke, was wilhelmtell bedeutet, ist, dass die C ++ - Standardbibliothek keine Container basierend auf ihrer zugrunde liegenden Datenstruktur definiert. Es definiert Container nur durch ihre Schnittstelle und beobachtbare Merkmale wie asymptotische Leistung. Wenn Sie darüber nachdenken, ist ein Baum überhaupt kein Container (wie wir sie kennen). Sie haben nicht einmal eine direkte end()und begin()mit der Sie alle Elemente usw. durchlaufen können
Jordan Melo
7
@ JordanMelo: Unsinn in allen Punkten. Es ist eine Sache, die Objekte enthält. Es ist sehr trivial, es so zu gestalten, dass es einen Anfang () und ein Ende () sowie bidirektionale Iteratoren zum Iterieren gibt. Jeder Behälter hat unterschiedliche Eigenschaften. Es wäre nützlich, wenn man zusätzlich Baummerkmale haben könnte. Sollte ziemlich einfach sein.
Mooing Duck
Daher möchte man einen Container haben, der schnelle Suchvorgänge für untergeordnete und übergeordnete Knoten sowie angemessene Speicheranforderungen bietet.
Doc
@JordanMelo: Aus dieser Perspektive würden auch Adapter wie Warteschlangen, Stapel oder Prioritätswarteschlangen nicht zur STL gehören (sie haben auch kein begin()und end()). Und denken Sie daran, dass eine Prioritätswarteschlange normalerweise ein Heap ist, der zumindest theoretisch ein Baum ist (obwohl es sich um tatsächliche Implementierungen handelt). Selbst wenn Sie einen Baum als Adapter mit einer anderen zugrunde liegenden Datenstruktur implementieren, kann er in die STL aufgenommen werden.
andreee
48

"Ich möchte eine Hierarchie von Objekten als Baum speichern"

C ++ 11 ist gekommen und gegangen und sie sahen immer noch keine Notwendigkeit, eine bereitzustellen std::tree, obwohl die Idee aufkam (siehe hier ). Vielleicht liegt der Grund dafür, dass sie dies nicht hinzugefügt haben, darin, dass es trivial einfach ist, eigene auf den vorhandenen Containern aufzubauen. Zum Beispiel...

template< typename T >
struct tree_node
   {
   T t;
   std::vector<tree_node> children;
   };

Eine einfache Durchquerung würde Rekursion verwenden ...

template< typename T >
void tree_node<T>::walk_depth_first() const
   {
   cout<<t;
   for ( auto & n: children ) n.walk_depth_first();
   }

Wenn Sie eine Hierarchie pflegen wollen und Sie wollen , dass es für die Arbeit mit STL - Algorithmen , dann können die Dinge kompliziert werden. Sie könnten Ihre eigenen Iteratoren erstellen und eine gewisse Kompatibilität erreichen, jedoch machen viele der Algorithmen für eine Hierarchie einfach keinen Sinn (alles, was beispielsweise die Reihenfolge eines Bereichs ändert). Sogar das Definieren eines Bereichs innerhalb einer Hierarchie kann ein chaotisches Geschäft sein.

kein Balken
quelle
2
Wenn das Projekt die Sortierung der untergeordneten Elemente eines tree_node ermöglichen kann, wird die Verwendung eines std :: set <> anstelle des std :: vector <> und das Hinzufügen eines Operators <() zum tree_node-Objekt erheblich verbessert 'Such'-Leistung eines' T'-ähnlichen Objekts.
J Jorgenson
4
Es stellt sich heraus, dass sie faul waren und tatsächlich Ihr erstes Beispiel für undefiniertes Verhalten gemacht haben.
user541686
2
@Mehrdad: Ich schließlich entschied sich für das Detail hinter Ihren Kommentar zu fragen hier .
Nobar
many of the algorithms simply don't make any sense for a hierarchy. Eine Frage der Interpretation. Stellen Sie sich eine Struktur von Stackoverflow-Benutzern vor, und jedes Jahr möchten Sie, dass Benutzer mit einer höheren Anzahl von Reputationspunkten diejenigen mit niedrigeren Reputationspunkten beherrschen. So erhalten Sie jedes Jahr einen BFS-Iterator und einen entsprechenden Vergleich std::sort(tree.begin(), tree.end()).
Doc
Aus dem gleichen Grunde konnte man leicht einen assoziativen Baum bauen (unstrukturierten Schlüssel-Wert - Datensätze zu modellieren, wie JSON zum Beispiel) durch den Austausch vectormit mapin dem obigen Beispiel. Zur vollständigen Unterstützung einer JSON-ähnlichen Struktur können Sie variantdie Knoten definieren.
Nobar
43

Wenn Sie nach einer RB-Tree-Implementierung suchen, ist stl_tree.h möglicherweise auch für Sie geeignet.

Systemfehler
quelle
14
Seltsamerweise ist dies die einzige Antwort, die tatsächlich die ursprüngliche Frage beantwortet.
Catskul
12
In Anbetracht dessen, dass er ein "Heiarchat" will, scheint es sicher anzunehmen, dass alles, was mit "Balancieren" zu tun hat, die falsche Antwort ist.
Mooing Duck
11
"Dies ist eine interne Header-Datei, die in anderen Bibliotheks-Headern enthalten ist. Sie sollten nicht versuchen, sie direkt zu verwenden."
Dan
3
@ Dan: Das Kopieren bedeutet nicht, es direkt zu verwenden.
Einpoklum
12

Die std :: map basiert auf einem rot-schwarzen Baum . Sie können auch andere Container verwenden , um Ihre eigenen Baumarten zu implementieren.

JJ
quelle
13
Es werden normalerweise rot-schwarze Bäume verwendet (dies ist nicht erforderlich).
Martin York
1
GCC verwendet einen Baum, um die Karte zu implementieren. Möchte jemand in seinem VC-Include-Verzeichnis nachsehen, was Microsoft verwendet?
JJ
// Rot-Schwarz-Baumklasse, die für die Implementierung von // assoziativen STL-Containern (Set, Multiset, Map und Multimap) entwickelt wurde. Habe das aus meiner Datei stl_tree.h geholt.
JJ
@JJ Zumindest in Studio 2010 wird eine interne ordered red-black tree of {key, mapped} values, unique keysKlasse verwendet, die in definiert ist <xtree>. Sie haben momentan keinen Zugriff auf eine modernere Version.
Justin Time - Stellen Sie Monica am
8

In gewisser Weise ist std :: map ein Baum (es muss dieselben Leistungsmerkmale wie ein ausgeglichener Binärbaum aufweisen), es werden jedoch keine anderen Baumfunktionen verfügbar gemacht. Die wahrscheinliche Begründung dafür, dass keine echte Baumdatenstruktur aufgenommen wurde, bestand wahrscheinlich nur darin, nicht alles in die stl aufzunehmen. Die stl kann als Framework für die Implementierung Ihrer eigenen Algorithmen und Datenstrukturen angesehen werden.

Wenn Sie eine grundlegende Bibliotheksfunktionalität wünschen, die nicht in der STL enthalten ist, sollten Sie sich im Allgemeinen BOOST ansehen .

Ansonsten gibt es ein Bündel von Bibliotheken aus dort , je nach den Bedürfnissen des Baumes.

Finsternis
quelle
6

Alle STL-Container werden extern als "Sequenzen" mit einem Iterationsmechanismus dargestellt. Bäume folgen dieser Redewendung nicht.

Emilio Garavaglia
quelle
7
Eine Baumdatenstruktur könnte eine Vorbestellungs-, Inorder- oder Postorder-Durchquerung über Iteratoren bereitstellen. Genau das macht std :: map.
Andrew Tomazos
3
Ja und nein ... es kommt darauf an, was du mit "Baum" meinst. std::mapwird intern als btree implementiert, aber extern erscheint es als sortierte Folge von Paaren. In Anbetracht des Elements können Sie allgemein fragen, wer vorher und wer nachher ist. Eine allgemeine Baumstruktur, die Elemente enthält, von denen jedes andere enthält, legt keine Sortierung oder Richtung fest. Sie können Iteratoren definieren, die eine Baumstruktur auf viele Arten durchlaufen (fahl | tief zuerst | zuletzt ...), aber sobald Sie dies getan haben, std::treemuss ein Container einen von ihnen von einer beginFunktion zurückgeben. Und es gibt keinen offensichtlichen Grund, den einen oder anderen zurückzugeben.
Emilio Garavaglia
4
Eine std :: map wird im Allgemeinen durch einen ausgeglichenen binären Suchbaum dargestellt, nicht durch einen B-Baum. Das gleiche Argument, das Sie vorgebracht haben, könnte für std :: unordered_set gelten. Es hat keine natürliche Reihenfolge, präsentiert jedoch Start- und Enditeratoren. Die Anforderung von Anfang und Ende ist nur, dass alle Elemente in einer deterministischen Reihenfolge iteriert werden, nicht dass es eine natürliche geben muss. Vorbestellung ist eine vollkommen gültige Iterationsreihenfolge für einen Baum.
Andrew Tomazos
4
Ihre Antwort impliziert, dass es keine stl n-Baum-Datenstruktur gibt, da es keine "Sequenz" -Schnittstelle gibt. Das ist einfach falsch.
Andrew Tomazos
3
@EmiloGaravaglia: Wie gezeigt std::unordered_set, hat dies keine "einzigartige Art", seine Mitglieder zu iterieren (tatsächlich ist die Iterationsreihenfolge pseudozufällig und die Implementierung definiert), ist aber immer noch ein stl-Container - dies widerlegt Ihren Standpunkt. Das Iterieren über jedes Element in einem Container ist immer noch eine nützliche Operation, selbst wenn die Reihenfolge undefiniert ist.
Andrew Tomazos
4

Weil die STL keine "Alles" -Bibliothek ist. Es enthält im Wesentlichen die Mindeststrukturen, die zum Bauen von Dingen erforderlich sind.

Paul Nathan
quelle
13
Binäre Bäume sind eine äußerst grundlegende Funktionalität und in der Tat grundlegender als andere Container, da Typen wie std :: map, std :: multimap und stl :: set. Da diese Typen auf ihnen basieren, würden Sie erwarten, dass der zugrunde liegende Typ verfügbar gemacht wird.
Catskul
2
Ich glaube nicht, dass das OP nach einem Binärbaum fragt , er fragt nach einem Baum, um eine Hierarchie zu speichern.
Mooing Duck
Nicht nur das, das Hinzufügen eines Baum- "Containers" zu STL hätte viele neue Konzepte hinzugefügt, zum Beispiel einen Baumnavigator (verallgemeinernder Iterator).
AlfC
5
"Minimale Strukturen, um Dinge zu bauen" ist eine sehr subjektive Aussage. Sie können Dinge mit rohen C ++ - Konzepten erstellen, also denke ich, dass ein echtes Minimum überhaupt keine STL wäre.
Doc
4

Dieser sieht vielversprechend aus und scheint das zu sein, wonach Sie suchen: http://tree.phi-sci.com/

roffez
quelle
3

IMO, eine Auslassung. Aber ich denke, es gibt gute Gründe, keine Baumstruktur in die STL aufzunehmen. Es gibt eine Menge von Logik in einen Baum gehalten wird , die sich am besten als geschrieben Member - Funktionen in das TreeNodeBasisobjekt . Wenn TreeNodees in einen STL-Header eingeschlossen ist, wird es nur noch unordentlicher.

Zum Beispiel:

template <typename T>
struct TreeNode
{
  T* DATA ; // data of type T to be stored at this TreeNode

  vector< TreeNode<T>* > children ;

  // insertion logic for if an insert is asked of me.
  // may append to children, or may pass off to one of the child nodes
  void insert( T* newData ) ;

} ;

template <typename T>
struct Tree
{
  TreeNode<T>* root;

  // TREE LEVEL functions
  void clear() { delete root ; root=0; }

  void insert( T* data ) { if(root)root->insert(data); } 
} ;
Bobobobo
quelle
7
Das ist eine Menge von rohen Zeigern, die Sie dort haben, von denen viele überhaupt keine Zeiger sein müssen.
Mooing Duck
Schlagen Sie vor, diese Antwort zurückzuziehen. Eine TreeNode-Klasse ist Teil einer Baumimplementierung.
Einpoklum
3

Ich denke, es gibt mehrere Gründe, warum es keine STL-Bäume gibt. In erster Linie sind Bäume eine Form der rekursiven Datenstruktur, die wie ein Container (Liste, Vektor, Menge) eine sehr unterschiedliche Feinstruktur aufweist, was die richtige Auswahl schwierig macht. Sie sind auch sehr einfach in Grundform mit der STL zu konstruieren.

Ein Baum mit endlichen Wurzeln kann als Container mit einem Wert oder einer Nutzlast betrachtet werden, beispielsweise als Instanz einer Klasse A und als möglicherweise leere Sammlung von verwurzelten (Unter-) Bäumen. Bäume mit leerer Sammlung von Teilbäumen werden als Blätter betrachtet.

template<class A>
struct unordered_tree : std::set<unordered_tree>, A
{};

template<class A>
struct b_tree : std::vector<b_tree>, A
{};

template<class A>
struct planar_tree : std::list<planar_tree>, A
{};

Man muss ein wenig über das Iterator-Design usw. nachdenken und darüber, welche Produkt- und Nebenproduktoperationen zwischen Bäumen definiert und effizient sein können - und die ursprüngliche STL muss gut geschrieben sein -, damit der leere Satz, Vektor oder Listencontainer vorhanden ist im Standardfall wirklich leer von jeglicher Nutzlast.

Bäume spielen in vielen mathematischen Strukturen eine wesentliche Rolle (siehe die klassischen Arbeiten von Butcher, Grossman und Larsen; auch die Arbeiten von Connes und Kriemer für Beispiele, wie sie zusammengefügt werden können und wie sie zur Aufzählung verwendet werden). Es ist nicht richtig zu glauben, dass ihre Rolle einfach darin besteht, bestimmte andere Operationen zu erleichtern. Sie erleichtern diese Aufgaben vielmehr aufgrund ihrer grundlegenden Rolle als Datenstruktur.

Neben Bäumen gibt es jedoch auch "Co-Bäume"; Die Bäume haben vor allem die Eigenschaft, dass Sie beim Löschen des Stamms alles löschen.

Betrachten Sie Iteratoren im Baum, wahrscheinlich würden sie als einfacher Stapel von Iteratoren für einen Knoten und dessen übergeordnetes Element bis zur Wurzel realisiert.

template<class TREE>
struct node_iterator : std::stack<TREE::iterator>{
operator*() {return *back();}
...};

Sie können jedoch so viele haben, wie Sie möchten. zusammen bilden sie einen "Baum", aber wo alle Pfeile in Richtung der Wurzel fließen, kann dieser Co-Baum durch Iteratoren in Richtung des trivialen Iterators und der Wurzel iteriert werden; Es kann jedoch nicht über oder nach unten navigiert werden (die anderen Iteratoren sind ihm nicht bekannt), und das Ensemble von Iteratoren kann nur gelöscht werden, wenn alle Instanzen im Auge behalten werden.

Bäume sind unglaublich nützlich, sie haben viel Struktur, was es zu einer ernsthaften Herausforderung macht, den definitiv richtigen Ansatz zu finden. Aus meiner Sicht sind sie deshalb nicht in der STL implementiert. Darüber hinaus habe ich in der Vergangenheit gesehen, wie Menschen religiös wurden und die Idee eines Containertyps mit Instanzen seines eigenen Typs als herausfordernd empfanden - aber sie müssen sich dem stellen - das ist, was ein Baumtyp darstellt - es ist ein Knoten, der a enthält möglicherweise leere Sammlung von (kleineren) Bäumen. Die aktuelle Sprache erlaubt es ohne Herausforderung, wenn der Standardkonstruktor für container<B>keinen Speicherplatz auf dem Heap (oder irgendwo anders) für ein Busw. reserviert .

Ich würde mich freuen, wenn dies in guter Form den Weg in den Standard finden würde.

tjl
quelle
0

Wenn man die Antworten hier durchliest, sind die häufig genannten Gründe, dass man den Baum nicht durchlaufen kann oder dass der Baum nicht die ähnliche Schnittstelle zu anderen STL-Containern annimmt und man keine STL-Algorithmen mit einer solchen Baumstruktur verwenden kann.

Vor diesem Hintergrund habe ich versucht, eine eigene Baumdatenstruktur zu entwerfen, die eine STL-ähnliche Schnittstelle bietet und so gut wie möglich mit vorhandenen STL-Algorithmen verwendet werden kann.

Meine Idee war, dass der Baum auf den vorhandenen STL-Containern basieren muss und dass er den Container nicht verbergen darf, damit er für die Verwendung mit STL-Algorithmen zugänglich ist.

Das andere wichtige Merkmal, das der Baum bereitstellen muss, sind die durchlaufenden Iteratoren.

Folgendes konnte ich mir einfallen lassen: https://github.com/igagis/utki/blob/master/src/utki/tree.hpp

Und hier sind die Tests: https://github.com/igagis/utki/blob/master/tests/tree/tests.cpp

Igagis
quelle
-9

Alle STL-Container können mit Iteratoren verwendet werden. Sie können keinen Iterator und keinen Baum haben, weil Sie keinen richtigen Weg haben, um durch den Baum zu gehen.

7890
quelle
3
Sie können jedoch sagen, dass BFS oder DFS der richtige Weg ist. Oder unterstützen Sie beide. Oder andere, die Sie sich vorstellen können. Sagen Sie dem Benutzer nur, was es ist.
Tomas789
2
In std :: map gibt es einen Baumiterator.
Jai
1
Ein Baum könnte seinen eigenen benutzerdefinierten Iteratortyp definieren, der alle Knoten in der Reihenfolge von einem "Extrem" zum anderen durchläuft (dh für jeden Binärbaum mit den Pfaden 0 und 1 könnte er einen Iterator anbieten, der von "alle Nullen" bis "alle" reicht 1s „und ein Rückwärts Iterator, der das Gegenteil tut, für einen Baum mit einer Tiefe von 3 und Startknoten s, zum Beispiel, es könnte den Knoten iterieren , wie s000, s00, s001, s0, s010, s01, s011, s, s100, s10, s101, s1, s110, s11, s111(“ am weitesten links stehenden“bis‚am weitesten rechts‘), sondern auch ein Tiefen traversal Muster (verwenden könnte s, s0, s1, s00, s01, s10, s11,
Justin Time - Stellen Sie Monica am
usw.) oder ein anderes Muster, solange es über jeden Knoten so iteriert, dass jeder nur ein einziges Mal übergeben wird.
Justin Time - Stellen Sie Monica am
1
@doc, sehr guter Punkt. Ich denke, es std::unordered_setwurde eine Sequenz "gemacht", weil wir keinen besseren Weg kennen, um über die Elemente zu iterieren, als einen beliebigen Weg (intern durch die Hash-Funktion vorgegeben). Ich denke, es ist der umgekehrte Fall des Baums: Die Iteration über unordered_setist unterbestimmt, theoretisch gibt es "keine Möglichkeit", eine andere Iteration als vielleicht "zufällig" zu definieren. Im Fall von Baum gibt es viele "gute" (nicht zufällige) Wege. Aber auch hier ist Ihr Punkt gültig.
AlfC