From 918ae1d61e3244167cd2c4396a3af89d2310768d Mon Sep 17 00:00:00 2001 From: LukVal54 Date: Thu, 11 Dec 2025 11:16:22 +0100 Subject: [PATCH] nextTreedata in order Traversierung --- bintree.c | 90 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/bintree.c b/bintree.c index c2b1c60..97c52b1 100644 --- a/bintree.c +++ b/bintree.c @@ -69,66 +69,90 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc // push the top node and push all its left nodes. // Wir brauchen eine statische Variable, die überdauernd existiert // (Alternativ kann man diese auch global ausserhalb definieren) -static Stack *iteratorStack = NULL; +// Die statische Variable (das Gedächtnis) muss außerhalb oder static innerhalb sein + +/* + * nextTreeData - Iterative In-Order Traversierung (wie strtok) + * * Funktionsweise: + * 1. Initialisierung (root != NULL): + * - Löscht alten Stack. + * - Wandert von root so weit nach LINKS wie möglich. + * - Pushed alle Knoten auf dem Weg auf den Stack. + * -> Das kleinste Element liegt nun oben. + * * 2. Iteration (root == NULL): + * - Pop: Nimmt oberstes Element vom Stack (aktuell kleinstes). + * - Logik: Hat dieses Element einen RECHTEN Nachbarn? + * -> JA: Gehe eins nach rechts, dann wieder alles nach LINKS pushen. + * -> NEIN: Nichts tun (der Elternknoten liegt schon als nächstes auf dem Stack). + * - Gibt die Daten des gepoppten Elements zurück. + */ +static StackNode *iteratorStack = NULL; void *nextTreeData(TreeNode *root) { - // --- FALL 1: Initialisierung (Neuer Baum wird übergeben) --- + // ============================================================ + // PHASE 1: Initialisierung (Neuer Baum wird übergeben) + // ============================================================ if (root != NULL) { - // Falls noch ein alter Stack da ist: Aufräumen! - // (Hängt von deiner stack.h ab, ob es clearStack oder ähnlich gibt) + // 1. Aufräumen: Falls noch Reste vom letzten Mal da sind if (iteratorStack != NULL) { - clearStack(iteratorStack); // oder freeStack, je nach Implementierung - iteratorStack = NULL; // Sicherstellen, dass er leer ist + clearStack(iteratorStack); + iteratorStack = NULL; // Wichtig: Zeiger "erden" } - // Neuen Stack erstellen (falls nötig) - // Angenommen, du hast eine Funktion wie createStack() oder initStack() - if (iteratorStack == NULL) { - iteratorStack = createStack(); // oder wie deine Init-Funktion heißt - } - - // Jetzt: "Push root and all left nodes" + // 2. Initial befüllen: "Push root and all left nodes" TreeNode *currentNode = root; while (currentNode != NULL) { - push(iteratorStack, currentNode); // Achtung: Funktionsname aus stack.h prüfen + // HIER war deine Frage: Ja, wir müssen iteratorStack aktualisieren! + // Wir casten TreeNode* implizit zu void* für den Stack. + iteratorStack = push(iteratorStack, currentNode); + + // Immer weiter nach links absteigen currentNode = currentNode->left; } - // Bei strtok gibt der erste Aufruf oft schon das erste Element zurück. - // Wir fallen also einfach in den Code unten rein (kein return hier). + // WICHTIG: Wir geben hier noch nichts zurück! + // Der erste Aufruf initialisiert nur. Um das erste Element zu bekommen, + // fällt der Code einfach weiter nach unten in Phase 2. } - // --- FALL 2: Fortsetzung (root ist NULL) --- - // Wenn der Stack leer ist, sind wir fertig mit dem Baum - if (iteratorStack == NULL || stackIsEmpty(iteratorStack)) // Name aus stack.h prüfen - { - return NULL; - } - - // 1. Nimm das oberste Element (das ist "dran") - TreeNode *nodeToReturn = pop(iteratorStack); // Name aus stack.h prüfen + // ============================================================ + // PHASE 2: Iteration (Nächsten Wert holen) + // ============================================================ - // Daten sichern, bevor wir weitermachen - void *data = nodeToReturn->data; + // Wenn der Stack leer ist (oder leer war), sind wir fertig. + if (iteratorStack == NULL) + { + return NULL; + } - // 2. Vorbereiten für das NÄCHSTE Mal: - // Wenn wir rechts abbiegen können, tun wir das. - // Die Regel ist: Einmal rechts, dann immer links runter. + // 1. Wir schauen uns das oberste Element an (der nächste Knoten in der Reihe) + // Wir wissen, dass es ein TreeNode* ist, also casten wir. + TreeNode *nodeToReturn = (TreeNode*) top(iteratorStack); + + // 2. Wir entfernen ihn vom Stack (er ist jetzt "verarbeitet") + // Auch hier: pop gibt den neuen Head zurück, also variable aktualisieren! + iteratorStack = pop(iteratorStack); + + // 3. Wir retten die Nutzer-Daten (z.B. den Integer), bevor wir weiterwandern + void *userData = nodeToReturn->data; + + // 4. Nachfolger suchen (Die Logik für In-Order: Rechts, dann alles links) if (nodeToReturn->right != NULL) { TreeNode *currentNode = nodeToReturn->right; - while (currentNode != NULL) { - push(iteratorStack, currentNode); + // Auch hier: Stack aktualisieren + iteratorStack = push(iteratorStack, currentNode); currentNode = currentNode->left; } } - return data; + // Wir geben die echten Daten zurück (nicht den Knoten, sondern den Inhalt) + return userData; } // Releases all memory resources (including data copies).