Baum kopieren
-
Hallo
@ Bashar :
Meine Anmerkung ist nicht witzig gemeint.
Da das ja nur ein Quellcode-Auszug ist und ich auch keinen anderen Fehler sehe als den vobn mir bemängelten, kann es ja sein er hat ja irgendwo eine Variable namens baum, die aber außer dem Root keinen weiteren Node hat (oder gar völlig ungültig ist). Und nun klont er versehentlich das falsche baum statt dem richtigen tree.bis bald
akari
-
Hi,
was meint Ihr mit Minimalbeispiel?
Also hier noch einmal meine Main.cpp:int main() { Baum baum; Read read; // Anfang Modul 1 string f = read.einlesen(); Baum *tree = new Baum(); if (f!="") { baum.insert(tree,f); cout << endl << endl; cout << "Baumstruktur (inorder)" << endl; baum.inorder(tree); cout << endl << endl; cout << "Baumstruktur (postorder)" << endl; baum.postorder(tree); cout << endl << endl; // Ende Modul 1 // Anfang Modul 2 Baum *tree2 = baum.clone(); baum.praedikate(tree); // HIER WIRD DER tree VERÄNDERT baum.belegung(); baum.aufruf(tree); baum.inorder(tree); cout << endl << endl; // DER VERÄNDERTE BAUM baum.inorder(tree2); // SOLLTE DER BAUM VOM ANFANG SEIN, IST ABER LEER } else { cout << "Formel falsch eingegeben, keine weitere bearbeitung moeglich" << endl; } system("PAUSE"); return EXIT_SUCCESS; }Also bisher habe ich noch nicht auf dem kopierten Baum gearbeitet. Wie auch, steht ja nix drin...
MfG, Ozzy
-
Ozzy schrieb:
was meint Ihr mit Minimalbeispiel?
Ein vollständiges Programm, was um alles unnütze reduziert wurde, aber dennoch das Problem gerade noch noch aufzeigt. Wenn du beim Reduzieren den Fehler findest, um so besser!
Mit sowas wie du gerade gepostet hast kann hier glaub ich keiner was anfangen, was macht z.B. baum.inorder(tree)? Ich weiß was ne Inorder-Traversierung ist, aber ich seh z.B. nicht, wieso du dazu zwei Bäume, baum und tree, brauchst. Man kann sich die Funktion der Methoden nicht logisch erschließen, also musst du sie posten.
-
Hi,
das finde ich etwas schwierig, aber ich kann ja mal probieren, es zu erklären. Also es fängt damit an, dass ich mich mit C++ kaum auskenne. Dieses Proggi soll dazu dienen, eine aussagenlogische Formel in einen Binärbaum "einrieseln" zu lassen, und anschließend seine Belegung zu ermitteln (also wann die Formel 1 ist).
Dieses "Baum baum" habe ich geschrieben, um die Funktionen in der Class Baum aufzurufen (z.B. inorder), so, wie ich es auch mit Read read gemacht habe, um von der main-methode die einlesen-Funktion der Formel aufzurufen.
Und tree habe ich eben den Baum genannt...Wie gesagt, ich kenne mich mit C++ kaum aus, aber vielleicht hilft ja schon das, was ich geschrieben habe, etwas aus...
MfG, Ozzy
-
Ozzy schrieb:
Dieses "Baum baum" habe ich geschrieben, um die Funktionen in der Class Baum aufzurufen (z.B. inorder), so, wie ich es auch mit Read read gemacht habe, um von der main-methode die einlesen-Funktion der Formel aufzurufen.
Und tree habe ich eben den Baum genannt...Ehrlich gesagt hab ich mir sowas schon gedacht. Du benutzt die Klasse Baum einerseits als Funktionssammlung und andererseits als Datenabstraktion, beides getrennt. Objektorientierte Programmierung funktioniert aber anders, beides ist zusammen in einem, das heißt, man sieht die Methoden als zum Objekt gehörig an. Dein Programm stelle ich mir eher so ungefähr vor:
Baum *tree = new Baum(); tree->insert(f); cout << endl << endl; cout << "Baumstruktur (inorder)" << endl; tree->inorder(); cout << endl << endl; cout << "Baumstruktur (postorder)" << endl; tree->postorder(); cout << endl << endl; // Ende Modul 1 // Anfang Modul 2 Baum *tree2 = tree->clone(); tree->praedikate(); // HIER WIRD DER tree VERÄNDERT tree->belegung(); tree->aufruf(); tree->inorder(); cout << endl << endl; // DER VERÄNDERTE BAUM tree2->inorder(); // SOLLTE DER BAUM VOM ANFANG SEIN ...Das Objekt baum, was bei dir nur der Funktionscontainer war, ist überflüssig. Du solltest deine Methoden so umschreiben, dass sie auf dem Objekt arbeiten, mit dem sie aufgerufen wurden. Beispielsweise sollte tree->inorder() das Objekt, auf das tree zeigt, inorder ausgeben, wahrscheinlich etwa so:
void Baum::inorder() const { if (left != 0) left->inorder(); cout << key << endl; if (right != 0) right->inorder(); }
-
Hi,
danke erst einmal, dann werde ich das mal ausprobieren.
Dann muss ich ja leider ne ganze Menge ändern...Meld mich dann noch mal, wenn ich soweit bin, MfG, Ozzy
-
Hi,
hab das mal ausprobiert, und er meckert bei mir gleich bei der Einfüge-Operation.
Hab hier mal ein bisserl Code aus der insert, vielelicht kannst Du mir ja noch einmal helfen, wie es wirklich heißen muss, damit ich dass dann so für die anderen Funktionen übernehmen kann:Baum::Baum(const Baum &baum) : left(baum.left ? baum.left->clone() : NULL), right(baum.right ? baum.right->clone() : NULL), key(baum.key) { return; }; string Baum::insert(Baum *&root, string f) { // fügt die Formen in den Baum ein int j=0; int k=0; bool leer=true; string ausdruck; cout << endl << "Element gelesen: " << f[s] << endl; // Gibt das gelesene Element aus if (root == 0) { // wenn Wurzel leer neuen Baum anfügen root = new Baum; root->left = root->right = 0; root->key = ""; // Schreibt erst einmal nichts in die Wurzel cout << "Wurzel erstellt" << endl; // Rückmeldung: Wurzel erstellt } if (f[s]==40) { // Wenn eine öffnende Klammer gefunden wurde s++; if (root->left==NULL) { // Wenn der linke Sohn NULL ist cout << "nach links" << endl; insert(root->left, f); // dann mache die Rekursion links } else { cout << "nach rechts (" << endl; insert(root->right, f); // ansonsten rechts } } // [...] }Vielen Dank schon einmal, Ozzy
-
Das kann man nicht mehr so einfach beantworten, das ist keine Frage mehr von richtig und falsch, sondern eine von Stil und Design. Deshalb ist das hier nur ein Vorschlag, wie ich es machen würde (vielleicht ist es auch vollkommen daneben
):class Baum { struct Node { string key; Node *left, *right; Node(); }; Node *root; // ... public: Baum(); string insert(const string& f); private: string insert_helper(Node*& root, const string& f); }; Baum::Node::Node() : left(0), right(0) {} Baum::Baum() : root(0) {} string Baum::insert(const string& f) { return insert_helper(root, f); } string Baum::insert_helper(Node*& root, const string& f) { // ... dein insert-Code }Die Trennung in Node und Baum wird IMO notwendig, weil es bei dir die Möglichkeit eines leeren Baumes als Nullpointer gibt, und ich wüsste nicht, wie man das direkt mit nur einer Klasse abbilden kann ... man kann ja schlecht insert auf einen Nullpointer aufrufen. Deshalb kapselt Baum den Baum als abstraktes Objekt, während Node die verkettete Struktur intern abbildet. An sich ist das nicht so weit entfernt von deinem bisherigen Design, es sollte sich relativ gut umsetzen lassen.
-
Hi,
also jetzt funzt gar nichts mehr...
Er meckert jetzt an der Inorder rum (request for member `inorder' in `std::left', which is of non-class type `std::ios_base&()(std::ios_base&)' ), er sagt, er habe kein left und kein right...
Also bei meiner Ahnung zerschieße ich mir da mehr, als ich gewinne...Gibt es echt keine andere Möglichkeit???
MfG, Ozzy
-
Die inorder-Prozedur, die ich letzte Woche gepostet habe, passt nicht mit obigem Design zusammen.
Du solltest versuchen, die Essenz dessen, was ich hier von mir gebe, zu verstehen und das Design deines Programms entsprechend zu ändern. Ich kann keinen Code posten, der 1:1 blind in dein jetziges Programm eingebaut werden kann und noch dazu alle deine Probleme löst. Erstens kenne ich zu wenig von deinem Programm, und zweitens hab ich dazu keine Zeit.