diff --git a/Double b/Double new file mode 160000 index 0000000..92bb8b7 --- /dev/null +++ b/Double @@ -0,0 +1 @@ +Subproject commit 92bb8b73d30806f24e365607346c2fa96a54d850 diff --git a/bintree.c b/bintree.c index 5cf82a9..638f8e5 100644 --- a/bintree.c +++ b/bintree.c @@ -1,3 +1,4 @@ +#include #include #include "stack.h" #include "bintree.h" @@ -12,7 +13,32 @@ // 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) { + if (root == NULL) { + TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode)); + if (node == NULL) return NULL; + node->data = malloc(dataSize); + if (node->data == NULL) { free(node); return NULL; } + memcpy(node->data, data, dataSize); + node->left = node->right = NULL; + if (isDuplicate) *isDuplicate = 0; + return node; + } + int cmp = compareFct(data, root->data); + if (cmp < 0) { + root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); + } else if (cmp > 0) { + root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } else { // cmp == 0 -> duplicate + if (isDuplicate) { + *isDuplicate = 1; + return root; + } else { + // accept duplicates when isDuplicate == NULL: insert to the right subtree + root->right = addToTree(root->right, data, dataSize, compareFct, NULL); + } + } + 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. @@ -20,17 +46,48 @@ 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) { + static StackNode *iterStack = NULL; + if (root != NULL) { + // (re)initialize iterator for new tree + clearStack(iterStack); + iterStack = NULL; + TreeNode *cur = root; + while (cur != NULL) { + iterStack = push(iterStack, cur); + cur = cur->left; + } + } + + if (iterStack == NULL) return NULL; + + TreeNode *node = (TreeNode *)top(iterStack); + iterStack = pop(iterStack); + void *ret = node->data; + + // push right subtree (and all its left descendants) + TreeNode *cur = node->right; + while (cur != NULL) { + iterStack = push(iterStack, cur); + cur = cur->left; + } + + return ret; } // Releases all memory resources (including data copies). void clearTree(TreeNode *root) { - + if (root == NULL) return; + clearTree(root->left); + clearTree(root->right); + free(root->data); + free(root); } // Returns the number of entries in the tree given by root. unsigned int treeSize(const TreeNode *root) { - + if (root == NULL) return 0; + return 1 + treeSize(root->left) + treeSize(root->right); } \ No newline at end of file diff --git a/bintree.o b/bintree.o new file mode 100644 index 0000000..5d9c075 Binary files /dev/null and b/bintree.o differ diff --git a/doble.exe b/doble.exe new file mode 100644 index 0000000..6120469 Binary files /dev/null and b/doble.exe differ diff --git a/highscore.o b/highscore.o new file mode 100644 index 0000000..ffbf6b0 Binary files /dev/null and b/highscore.o differ diff --git a/highscores.txt b/highscores.txt index 4edd5a7..b89d2a8 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1 +1,4 @@ +player_name;11898 +Test;9953 +player_name;9927 player1;3999 diff --git a/main.o b/main.o new file mode 100644 index 0000000..93deeec Binary files /dev/null and b/main.o differ diff --git a/numbers.c b/numbers.c index f59d9a2..26c5c7d 100644 --- a/numbers.c +++ b/numbers.c @@ -5,22 +5,95 @@ #include "numbers.h" #include "bintree.h" -//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. */ +static int compareUnsigned(const void *a, const void *b) +{ + unsigned int va = *(const unsigned int *)a; + unsigned int vb = *(const unsigned int *)b; + if (va < vb) return -1; + if (va > vb) return 1; + return 0; +} // 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. unsigned int *createNumbers(unsigned int len) { + if (len < 2) return NULL; + unsigned int *arr = (unsigned int *)malloc(len * sizeof(unsigned int)); + if (arr == NULL) return NULL; + + TreeNode *root = NULL; + /* create len-1 unique values in range [1, 2*len] */ + srand((unsigned int)time(NULL)); + + while (treeSize(root) < len - 1) { + unsigned int v = (unsigned int)(rand() % (2 * len)) + 1; + int isDup = 0; + TreeNode *newRoot = addToTree(root, &v, sizeof(unsigned int), compareUnsigned, &isDup); + if (newRoot == NULL && root != NULL) { // allocation failed + clearTree(root); + free(arr); + return NULL; + } + root = newRoot; + /* if duplicate, addToTree left tree unchanged; loop continues */ + } + + /* extract values from tree (in-order) into arr[0..len-2] */ + unsigned int idx = 0; + void *data = nextTreeData(root); // initializes iterator + while (data != NULL && idx < len - 1) { + arr[idx++] = *(unsigned int *)data; + data = nextTreeData(NULL); + } + + if (idx != len - 1) { + clearTree(root); + free(arr); + return NULL; + } + + /* pick a random existing index and duplicate it */ + unsigned int dupIndex = (unsigned int)(rand() % (len - 1)); + arr[len - 1] = arr[dupIndex]; + + /* free tree memory */ + clearTree(root); + + /* shuffle array */ + for (unsigned int i = len - 1; i > 0; --i) { + unsigned int j = (unsigned int)(rand() % (i + 1)); + unsigned int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + return arr; } // 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) { + if (numbers == NULL || len < 2) return 0; + TreeNode *root = NULL; + for (unsigned int i = 0; i < len; ++i) { + unsigned int v = numbers[i]; + int isDup = 0; + TreeNode *newRoot = addToTree(root, &v, sizeof(unsigned int), compareUnsigned, &isDup); + if (newRoot == NULL && root != NULL) { // allocation failed + clearTree(root); + return 0; + } + root = newRoot; + if (isDup) { + clearTree(root); + return v; + } + } + + clearTree(root); + return 0; } \ No newline at end of file diff --git a/numbers.o b/numbers.o new file mode 100644 index 0000000..fa6b51a Binary files /dev/null and b/numbers.o differ diff --git a/stack.c b/stack.c index e3a90d4..6970da5 100644 --- a/stack.c +++ b/stack.c @@ -1,33 +1,39 @@ #include #include "stack.h" -//TODO: grundlegende Stackfunktionen implementieren: -/* * `push`: legt ein Element oben auf den Stack, - * `pop`: entfernt das oberste Element, - * `top`: liefert das oberste Element zurück, - * `clearStack`: gibt den gesamten Speicher frei. */ - // Pushes data as pointer onto the stack. StackNode *push(StackNode *stack, void *data) { - + StackNode *node = (StackNode*)malloc(sizeof(StackNode)); + if (node == NULL) return stack; // allocation failed, return unchanged stack + node->data = data; + node->next = stack; + return node; } // Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be // freed by caller.) StackNode *pop(StackNode *stack) { - + if (stack == NULL) return NULL; + StackNode *next = stack->next; + free(stack); + return next; } // Returns the data of the top element. void *top(StackNode *stack) { - + return (stack != NULL) ? stack->data : NULL; } // Clears stack and releases all memory. void clearStack(StackNode *stack) { - + while (stack != NULL) + { + StackNode *next = stack->next; + free(stack); + stack = next; + } } \ No newline at end of file diff --git a/stack.h b/stack.h index f7d542d..8f8824b 100644 --- a/stack.h +++ b/stack.h @@ -8,6 +8,10 @@ The latest element is taken from the stack. */ #include //TODO: passenden Datentyp als struct anlegen +typedef struct StackNode { + void *data; + struct StackNode *next; +} StackNode; // Pushes data as pointer onto the stack. StackNode *push(StackNode *stack, void *data); diff --git a/stack.o b/stack.o new file mode 100644 index 0000000..a4b3089 Binary files /dev/null and b/stack.o differ diff --git a/timer.o b/timer.o new file mode 100644 index 0000000..248a165 Binary files /dev/null and b/timer.o differ