diff --git a/bintree.c b/bintree.c index 5cf82a9..4cecb66 100644 --- a/bintree.c +++ b/bintree.c @@ -1,18 +1,82 @@ #include #include "stack.h" #include "bintree.h" +#include -//TODO: binären Suchbaum implementieren +// TODO: binären Suchbaum implementieren /* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), - * `clearTree`: gibt den gesamten Baum frei (rekursiv), - * `treeSize`: zählt die Knoten im Baum (rekursiv), - * `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ + * `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 // 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) { + TreeNode *insertedNode; + // create a new node if the current node is NULL + if (root == NULL) + { + // it's important to zero the pointers for adjacent nodes + insertedNode = calloc(1, sizeof(TreeNode)); + if (!insertedNode) + { + return NULL; + } + + insertedNode->data = malloc(dataSize); + if (!insertedNode->data) + { + return NULL; + } + memcpy(insertedNode->data, data, dataSize); + // reset isDuplicate if it exists + if (isDuplicate) + { + *isDuplicate = 0; + } + return insertedNode; + } + + // TODO: what is the correct data type here? + int cmpRes = (*compareFct)(data, root->data); + // insert into the left branch + if (cmpRes < 0 || (cmpRes == 0 && isDuplicate == NULL)) + { + root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); + } + // insert into the right branch + else if (cmpRes > 0) + { + root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } + // the data is equal to the current node + else + { + // the data already exists in the tree and duplicates are ignored (isDuplicate* not NULL) + *isDuplicate = 1; + } + return root; +} + +// push all left descendants from @param node +static void pushLeftDesc(StackNode **stackPtr, TreeNode *node) +{ + if (!stackPtr || !node) + { + return; + } + TreeNode *curNode = node; + while (curNode->left) + { + *stackPtr = push(*stackPtr, curNode->left); + if (!*stackPtr) + { + return; + } + curNode = curNode->left; + } } // 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. @@ -20,17 +84,72 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc // push the top node and push all its left nodes. void *nextTreeData(TreeNode *root) { + // this creates a static variable that maintains an internal state + static StackNode *stack; + // create a new stack + if (root) + { + // clear possibly existing stacks + clearStack(stack); + // init a new stack + stack = push(NULL, root); + // init failed + if (!stack) + { + return NULL; + } + pushLeftDesc(&stack, root); + + // return the first val + return nextTreeData(NULL); + } + + // neither stack nor root exist + if (!stack) + { + return NULL; + } + + // get next val with stack + TreeNode *res = top(stack); + stack = pop(stack); + if (res->right) + { + stack = push(stack, res->right); + pushLeftDesc(&stack, res->right); + } + + return res->data; } // Releases all memory resources (including data copies). void clearTree(TreeNode *root) { + // this check is crucial for recursion + if (!root) + { + // nothing to clear + return; + } + // release the resources of child nodes first + clearTree(root->left); + clearTree(root->right); + + // free the data (it's just a copy created in addToTree()) + free(root->data); + free(root); } // Returns the number of entries in the tree given by root. unsigned int treeSize(const TreeNode *root) { + // there are no nodes + if (!root) + { + return 0; + } + return 1 + treeSize(root->left) + treeSize(root->right); } \ No newline at end of file diff --git a/numbers.c b/numbers.c index 9387524..0a48b4d 100644 --- a/numbers.c +++ b/numbers.c @@ -18,17 +18,23 @@ unsigned int *createNumbers(unsigned int len) for (unsigned int i = 0; i < len; i++) { do - { + { + isDuplicate = 0; numbers[i] = rand () % upperLimit + 1; binTree = addToTree(binTree, &numbers[i], sizeof(unsigned int), compare, &isDuplicate); } while (isDuplicate); } unsigned int duplicate = numbers[rand () % len]; - int indexDuplicate = rand () % len; - numbers[len] = numbers[indexDuplicate]; - numbers[indexDuplicate] = duplicate; + int indexDuplicate; + do { + indexDuplicate = rand() % len; + } while (numbers[indexDuplicate] == duplicate); + + numbers[len-1] = numbers[indexDuplicate]; + numbers[indexDuplicate] = duplicate; + return numbers; }