From 23dccdfd8dabb6378c650c4ea79b379b8192b441 Mon Sep 17 00:00:00 2001 From: muellermo100295 Date: Wed, 10 Dec 2025 22:43:39 +0100 Subject: [PATCH] =?UTF-8?q?Kommentare=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bintree.c | 159 +++++++++++++++++++++++++++++++++--------------------- bintree.h | 76 ++++++++++++++++++++++---- 2 files changed, 163 insertions(+), 72 deletions(-) diff --git a/bintree.c b/bintree.c index 668c164..91f0430 100644 --- a/bintree.c +++ b/bintree.c @@ -1,111 +1,148 @@ + #include #include #include "stack.h" #include "bintree.h" -// internal helper to push node and all its left descendants onto iterator stack -static void bintree_pushLefts(StackNode **iterStackPtr, TreeNode *n) +/* + Schiebt einen Knoten und alle seine linken Nachfolger + (entlang der "linken Kante") auf den Iterator-Stack. + iterStackPtr: Zeiger auf den Top-Zeiger des Stacks (LIFO) für die Wiederholung + knoten: aktueller Startknoten, dessen linke Kette abgelegt wird +*/ +static void bintree_pushLefts(StackNode **iterStackPtr, TreeNode *knoten) { - while(n != NULL) + while (knoten != NULL) { - *iterStackPtr = push(*iterStackPtr, n); - n = n->left; + *iterStackPtr = push(*iterStackPtr, knoten); // aktuellen Knoten oben auf den Stack legen + knoten = knoten->left; // zum linken Kind weiterlaufen } } -// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates -// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). -TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) +/* + Fügt eine Kopie der Daten (Speicherbereich von 'data' mit Länge 'dataSize') in den Baum ein. + Die Ordnung wird über 'compareFct' festgelegt. + + Duplikate: + - Wenn 'isDuplicate' != NULL übergeben wird: Duplikate werden NICHT eingefügt, + stattdessen wird *isDuplicate = 1 gesetzt (bei neuem Eintrag = 0). + - Wenn 'isDuplicate' == NULL: Duplikate SIND erlaubt; der Duplikat-Eintrag + wird in den rechten Teilbaum eingefügt. + + Rückgabe: + - Zeiger auf die (ggf. unveränderte oder neue) Wurzel des Teilbaums. + - NULL bei Speicherfehlern beim Anlegen des ersten Knotens. +*/ +TreeNode *addToTree(TreeNode *wurzel, + const void *daten, + size_t datenGroesse, + CompareFctType vergleichFkt, + int *istDuplikat) { - if(isDuplicate != NULL) - *isDuplicate = 0; + // Standardmäßig annehmen: kein Duplikat (falls Ausgabefeld vorhanden) + if (istDuplikat != NULL) + *istDuplikat = 0; - if(root == NULL) + // Leerer Baum/Teilbaum: neuen Knoten erzeugen + if (wurzel == NULL) { - TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode)); - if(node == NULL) - return NULL; - node->data = malloc(dataSize); - if(node->data == NULL) + TreeNode *neuerKnoten = (TreeNode *)malloc(sizeof(TreeNode)); + if (neuerKnoten == NULL) + return NULL; // Speicherfehler + + neuerKnoten->data = malloc(datenGroesse); + if (neuerKnoten->data == NULL) { - free(node); - return NULL; + free(neuerKnoten); + return NULL; // Speicherfehler für Datenbereich } - memcpy(node->data, data, dataSize); - node->left = node->right = NULL; - return node; + + memcpy(neuerKnoten->data, daten, datenGroesse); // tiefe Kopie der Nutzdaten + neuerKnoten->left = neuerKnoten->right = NULL; // Blatt + return neuerKnoten; } - int cmp = compareFct(data, root->data); - if(cmp < 0) + // Vergleich der einzufügenden Daten mit dem aktuellen Knoten + int vergleich = vergleichFkt(daten, wurzel->data); + + if (vergleich < 0) { - root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); + // links einfügen + wurzel->left = addToTree(wurzel->left, daten, datenGroesse, vergleichFkt, istDuplikat); } - else if(cmp > 0) + else if (vergleich > 0) { - root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + // rechts einfügen + wurzel->right = addToTree(wurzel->right, daten, datenGroesse, vergleichFkt, istDuplikat); } - else // equal + else { - if(isDuplicate != NULL) + // Gleichheit (potenzielles Duplikat) + if (istDuplikat != NULL) { - *isDuplicate = 1; - // do not insert duplicate + *istDuplikat = 1; // Duplikat erkannt, NICHT einfügen + // keine Änderung am Baum } else { - // duplicates allowed -> insert into right subtree - root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + // Duplikate erlaubt -> konventionell in den rechten Teilbaum einfügen + wurzel->right = addToTree(wurzel->right, daten, datenGroesse, vergleichFkt, istDuplikat); } } - return root; + return wurzel; } -// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. -// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, -// push the top node and push all its left nodes. -void *nextTreeData(TreeNode *root) +void *nextTreeData(TreeNode *wurzel) { - static StackNode *iterStack = NULL; + static StackNode *iteratorStack = NULL; // interner Zustand über Aufrufe hinweg - // If a new tree root is provided -> reset iterator - if(root != NULL) + // Neuer Baum übergeben -> Iterator zurücksetzen/initialisieren + if (wurzel != NULL) { - clearStack(iterStack); - iterStack = NULL; - bintree_pushLefts(&iterStack, root); + clearStack(iteratorStack); // ggf. alten Stack leeren (Speicher freigeben) + iteratorStack = NULL; // Top-Zeiger zurücksetzen + bintree_pushLefts(&iteratorStack, wurzel); // Wurzel und linke Kette ablegen } - if(iterStack == NULL) + // Kein weiterer Eintrag? + if (iteratorStack == NULL) return NULL; - TreeNode *node = (TreeNode *)top(iterStack); - iterStack = pop(iterStack); + // Nächsten Knoten holen (oberstes Stack-Element) + TreeNode *aktuellerKnoten = (TreeNode *)top(iteratorStack); + iteratorStack = pop(iteratorStack); - if(node->right != NULL) - bintree_pushLefts(&iterStack, node->right); + // Falls rechter Teilbaum existiert: dessen linke Kette ablegen + if (aktuellerKnoten->right != NULL) + bintree_pushLefts(&iteratorStack, aktuellerKnoten->right); - return node->data; + // Daten des aktuellen Knotens zurückgeben + return aktuellerKnoten->data; } -// Releases all memory resources (including data copies). -void clearTree(TreeNode *root) +/* + Gibt den gesamten Baum frei (inkl. der tief kopierten Daten). +*/ +void clearTree(TreeNode *wurzel) { - if(root == NULL) + if (wurzel == NULL) return; - clearTree(root->left); - clearTree(root->right); + clearTree(wurzel->left); + clearTree(wurzel->right); - free(root->data); - free(root); + free(wurzel->data); + free(wurzel); } -// Returns the number of entries in the tree given by root. -unsigned int treeSize(const TreeNode *root) +/* + Liefert die Anzahl der Knoten/Einträge im Teilbaum 'wurzel'. +*/ +unsigned int treeSize(const TreeNode *wurzel) { - if(root == NULL) + if (wurzel == NULL) return 0; - return 1 + treeSize(root->left) + treeSize(root->right); -} \ No newline at end of file + + return 1U + treeSize(wurzel->left) + treeSize(wurzel->right); +} diff --git a/bintree.h b/bintree.h index 25e16b2..7ea1ff1 100644 --- a/bintree.h +++ b/bintree.h @@ -1,27 +1,81 @@ + #ifndef BINTREE_H #define BINTREE_H #include +/* + Typdefinition für die Vergleichsfunktion. + + Die Funktion muss zwei Datenzeiger vergleichen und zurückgeben: + - < 0, wenn arg1 kleiner als arg2 ist + - 0, wenn arg1 gleich arg2 ist + - > 0, wenn arg1 größer als arg2 ist +*/ typedef int (*CompareFctType)(const void *arg1, const void *arg2); +/* + Struktur für einen Binärbaum-Knoten. + + Enthält: + - data: Zeiger auf die gespeicherten Daten (beliebiger Typ, dynamisch allokiert) + - left: Zeiger auf linken Teilbaum + - right: Zeiger auf rechten Teilbaum +*/ typedef struct node { - void *data; - struct node *left; - struct node *right; + void *data; // Zeiger auf die Nutzdaten + struct node *left; // Zeiger auf linken Kindknoten + struct node *right; // Zeiger auf rechten Kindknoten } TreeNode; -// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates -// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). +/* + Fügt eine Kopie der Daten in den Binärbaum ein. + + Parameter: + root : Wurzel des (Teil-)Baums + data : Zeiger auf die einzufügenden Daten + dataSize : Größe der Daten in Bytes + compareFct : Vergleichsfunktion für die Ordnung + isDuplicate : Optionaler Zeiger: + - Wenn NULL: Duplikate sind erlaubt + - Wenn != NULL: Duplikate werden ignoriert und *isDuplicate wird gesetzt: + - 0: neuer Eintrag eingefügt + - 1: Duplikat erkannt, nicht eingefügt + + Rückgabe: + Zeiger auf die (ggf. neue) Wurzel des Baums oder NULL bei Speicherfehler. +*/ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate); -// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. -// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, -// push the top node and push all its left nodes. + +/* + Iteriert über den Baum in Inorder-Reihenfolge. + + Verhalten: + - Erster Aufruf mit root != NULL: Iterator initialisieren + - Folgeaufrufe mit root == NULL: nächstes Element zurückgeben + + Rückgabe: + Zeiger auf die Daten des nächsten Knotens oder NULL, wenn Ende erreicht. + + Hinweis: + Intern wird ein Stack verwendet. Nicht threadsicher. +*/ void *nextTreeData(TreeNode *root); -// Releases all memory resources (including data copies). + +/* + Gibt den gesamten Baum frei (inklusive der gespeicherten Daten). + + Nach dem Aufruf sind alle Zeiger ungültig. +*/ void clearTree(TreeNode *root); -// Returns the number of entries in the tree given by root. + +/* + Liefert die Anzahl der Knoten im Baum. + + Rückgabe: + Anzahl der Knoten (0 bei leerem Baum). +*/ unsigned int treeSize(const TreeNode *root); -#endif \ No newline at end of file +#endif