bintree implementiert

This commit is contained in:
Jan Uhlmann 2025-12-08 16:04:33 +01:00
parent afe2c3b90d
commit c2c94cd71d

109
bintree.c
View File

@ -1,36 +1,117 @@
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "stack.h" #include "stack.h"
#include "bintree.h" #include "bintree.h"
//TODO: binären Suchbaum implementieren static StackNode *iterStack = NULL;
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), static void pushLeftBranch(StackNode **stack, TreeNode *node);
* `clearTree`: gibt den gesamten Baum frei (rekursiv),
* `treeSize`: zählt die Knoten im Baum (rekursiv),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates // Inserts a new node into the BST.
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). // If isDuplicate == NULL → duplicates are allowed
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) // If isDuplicate != NULL → duplicates are ignored and *isDuplicate = 1
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
CompareFctType compareFct, int *isDuplicate)
{ {
if (root == NULL)
{
TreeNode *newNode = calloc(1, sizeof(TreeNode));
if (!newNode)
return NULL;
newNode->data = malloc(dataSize);
if (!newNode->data)
{
free(newNode);
return NULL;
}
memcpy(newNode->data, data, dataSize);
if (isDuplicate)
*isDuplicate = 0;
return newNode;
}
int cmp = compareFct(data, root->data);
if (cmp < 0 || (cmp == 0 && isDuplicate == NULL))
{
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else if (cmp > 0)
{
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
else
{
if (isDuplicate)
*isDuplicate = 1;
}
return root;
} }
// 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. static void pushLeftBranch(StackNode **stack, TreeNode *node)
// 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. while (node)
{
*stack = push(*stack, node);
node = node->left;
}
}
// If root != NULL → reset iterator and start from new tree.
// If root == NULL → continue iterating.
void *nextTreeData(TreeNode *root) void *nextTreeData(TreeNode *root)
{ {
// Start new iteration
if (root != NULL)
{
// reset old iterator state
clearStack(iterStack);
iterStack = NULL;
// push root and all left children
pushLeftBranch(&iterStack, root);
}
// No active iterator
if (iterStack == NULL)
return NULL;
// Get next node
TreeNode *node = (TreeNode *)top(iterStack);
iterStack = pop(iterStack);
// push right subtree and its left descendants
if (node->right)
pushLeftBranch(&iterStack, node->right);
return node->data;
} }
// Releases all memory resources (including data copies). // Frees all nodes and also resets iterator.
void clearTree(TreeNode *root) void clearTree(TreeNode *root)
{ {
if (!root)
return;
clearTree(root->left);
clearTree(root->right);
free(root->data);
free(root);
// If we clear the tree, iterator must not point into freed memory.
clearStack(iterStack);
iterStack = NULL;
} }
// Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root) unsigned int treeSize(const TreeNode *root)
{ {
if (!root)
return 0;
} return 1 + treeSize(root->left) + treeSize(root->right);
}