diff --git a/bintree.c b/bintree.c index 4cecb66..5cf82a9 100644 --- a/bintree.c +++ b/bintree.c @@ -1,82 +1,18 @@ #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. @@ -84,72 +20,17 @@ static void pushLeftDesc(StackNode **stackPtr, TreeNode *node) // 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 5211acb..f59d9a2 100644 --- a/numbers.c +++ b/numbers.c @@ -5,87 +5,22 @@ #include "numbers.h" #include "bintree.h" -static int compareInt(const void *ptr1, const void *ptr2); - -// TODO: getDuplicate und createNumbers implementieren +//TODO: getDuplicate und createNumbers implementieren /* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. - * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. - * Duplizieren eines zufälligen Eintrags im Array. - * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ + * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. + * Duplizieren eines zufälligen Eintrags im Array. + * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ // Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. // Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while // creating random numbers. - -/* -the implemented tree can't efficiently check if it contains a specific number, but we don't actually need that anyways -create numbers just counts and checks if the just inserted number sets the isDuplicate pointer -*/ -// srand should have been called before this function unsigned int *createNumbers(unsigned int len) { - unsigned int *randomNumbers = malloc(len * sizeof(int)); - if (!randomNumbers) - { - return NULL; - } - - // including upper limit - int upperLimit = len * 2; - - int numberCnt = 0; - - int isDuplicate = 0; - TreeNode *root = NULL; - // we only need len-1 numbers because 1 will be duplicated - while (numberCnt < len - 1) - { - // numbers up to and including upperLimit without 0 - int randNum = rand() % upperLimit + 1; - // reset isDuplicate - isDuplicate = 0; - // don't forget to set the root here - root = addToTree(root, &randNum, sizeof(randNum), (CompareFctType)compareInt, &isDuplicate); - if (isDuplicate) - { - // number already exists - continue; - } - randomNumbers[numberCnt++] = randNum; - } - - // select which number to duplicate - int dupNum = randomNumbers[rand() % numberCnt]; - // ...and where to insert - int dupNumIdx = rand() % len; - - // move the number currently at the dupNumIdx to the end - // and insert the dupNum at the index - // this also works if the last idx was selected for dupNum - randomNumbers[len - 1] = randomNumbers[dupNumIdx]; - randomNumbers[dupNumIdx] = dupNum; - - // clean up memory - clearTree(root); - return randomNumbers; } // Returns only the only number in numbers which is present twice. Returns zero on errors. unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { - qsort((void *)numbers, len, sizeof(int), compareInt); // sort the array - for (int i = 0; i < len - 1; i++) - { - if (numbers[i] == numbers[i + 1]) - return numbers[i]; - } - return 0; // zero on errors -} -static int compareInt(const void *ptr1, const void *ptr2) -{ - int num1 = *(int *)ptr1; - int num2 = *(int *)ptr2; - return num1 - num2; } \ No newline at end of file