This commit is contained in:
F A 2025-12-08 14:00:19 +01:00
parent 25085b3778
commit 81e1483e9e
18 changed files with 368 additions and 72 deletions

131
bintree.c
View File

@ -1,36 +1,129 @@
#include <stdlib.h>
#include <string.h>
#include "stack.h"
#include "bintree.h"
//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. */
// --------------------------
// Hilfsfunktion für Vergleich von unsigned int
// --------------------------
static int compareUint(const void *a, const void *b)
{
unsigned int x = *(unsigned int *)a;
unsigned int y = *(unsigned int *)b;
if (x < y) return -1;
if (x > y) return 1;
return 0;
}
// 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).
// --------------------------
// addToTree
// --------------------------
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{
if (!compareFct)
compareFct = compareUint;
}
// 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)
if (!root)
{
TreeNode *node = malloc(sizeof(TreeNode));
if (!node) return NULL;
node->data = malloc(dataSize);
if (!node->data)
{
free(node);
return NULL;
}
memcpy(node->data, data, dataSize);
node->left = node->right = NULL;
if (isDuplicate) *isDuplicate = 0;
return node;
}
// Releases all memory resources (including data copies).
int cmp = compareFct(data, root->data);
if (cmp == 0)
{
if (isDuplicate) *isDuplicate = 1;
return root;
}
else if (cmp < 0)
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
else
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
return root;
}
// --------------------------
// clearTree
// --------------------------
void clearTree(TreeNode *root)
{
if (!root) return;
clearTree(root->left);
clearTree(root->right);
free(root->data);
free(root);
}
// Returns the number of entries in the tree given by root.
// --------------------------
// treeSize
// --------------------------
unsigned int treeSize(const TreeNode *root)
{
if (!root) return 0;
return 1 + treeSize(root->left) + treeSize(root->right);
}
// --------------------------
// nextTreeData (In-Order Traversal mit Stack) minimal
// --------------------------
#include "stack.h"
void *nextTreeData(TreeNode *root)
{
static StackNode *stack = NULL;
static TreeNode *current = NULL;
if (root) current = root;
while (current)
{
stack = push(stack, current);
current = current->left;
}
if (!stack) return NULL;
TreeNode *node = top(stack);
stack = pop(stack);
current = node->right;
return node->data;
}
// --------------------------
// Zusätzliche Hilfsfunktion contains für numbers.c
// --------------------------
int contains(TreeNode *root, unsigned int value)
{
if (!root) return 0;
unsigned int nodeValue = *(unsigned int *)root->data;
if (value == nodeValue) return 1;
if (value < nodeValue) return contains(root->left, value);
return contains(root->right, value);
}
// --------------------------
// Hilfsfunktion insert für numbers.c
// --------------------------
TreeNode* insert(TreeNode *root, unsigned int value)
{
int isDup = 0;
return addToTree(root, &value, sizeof(unsigned int), compareUint, &isDup);
}
// --------------------------
// Hilfsfunktion freeTree für numbers.c
// --------------------------
void freeTree(TreeNode *root)
{
clearTree(root);
}

BIN
bintree.o Normal file

Binary file not shown.

BIN
doble.exe Normal file

Binary file not shown.

BIN
doble_initial.exe Normal file

Binary file not shown.

BIN
highscore.o Normal file

Binary file not shown.

View File

@ -1 +1,10 @@
player_name1;19827
player_name3;6985
jannik;5979
jannik;4991
jannik;4980
player1;3999
player_name;3995
player_name2;3994
player_name1;3993
player_name3;3990

BIN
main.o Normal file

Binary file not shown.

View File

@ -16,34 +16,68 @@ raylibfolder = ./raylib
unityfolder = ./unity
# --------------------------
# Initiales Programm bauen (zum ausprobieren)
# Hauptprogramm bauen
# --------------------------
doble_initial:
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
# --------------------------
# Selbst implementiertes Programm bauen
# --------------------------
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
doble: main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble
main.o: main.c
$(CC) -c $(FLAGS) main.c -o main.o
$(program_obj_filesobj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@
# --------------------------
# Unit Tests
# --------------------------
unitTests:
echo "needs to be implemented"
unitTests: test_stack test_numbers
./test_stack
./test_numbers
# --- Test Stack ---
test_stack: test_stack.o stack.o
$(CC) $(FLAGS) $^ -o test_stack
test_stack.o: test_stack.c stack.h
$(CC) -c $(FLAGS) test_stack.c -o test_stack.o
# --- Test Numbers ---
test_numbers: test_numbers.o numbers.o bintree.o stack.o
$(CC) $(FLAGS) $^ -o test_numbers
test_numbers.o: test_numbers.c numbers.h
$(CC) -c $(FLAGS) test_numbers.c -o test_numbers.o
# --------------------------
# Objektdateien
# --------------------------
stack.o: stack.c stack.h
$(CC) -c $(FLAGS) stack.c -o stack.o
bintree.o: bintree.c bintree.h stack.h
$(CC) -c $(FLAGS) bintree.c -o bintree.o
numbers.o: numbers.c numbers.h bintree.h
$(CC) -c $(FLAGS) numbers.c -o numbers.o
timer.o: timer.c timer.h
$(CC) -c $(FLAGS) timer.c -o timer.o
highscore.o: highscore.c highscore.h
$(CC) -c $(FLAGS) highscore.c -o highscore.o
# --------------------------
# Clean
# --------------------------
clean:
ifeq ($(OS),Windows_NT)
del /f *.o doble
del /f *.o doble test_stack test_numbers
else
rm -f *.o doble
rm -f *.o doble test_stack test_numbers
endif

View File

@ -5,22 +5,83 @@
#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. */
// 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)
{
// Hilfsfunktion zum Vergleichen von ints für Baum
static int compareInt(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
// 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)
{
// Vergleichsfunktion für qsort (unsigned int, überlauf-sicher)
static int compareUnsigned(const void *a, const void *b) {
unsigned int ua = *(unsigned int*)a;
unsigned int ub = *(unsigned int*)b;
if (ua < ub) return -1;
if (ua > ub) return 1;
return 0;
}
// Hilfsfunktion: Prüft, ob Wert schon im Baum ist
static int contains(TreeNode *root, unsigned int value) {
if (!root) return 0;
unsigned int val = *(unsigned int*)root->data;
if (val == value) return 1;
if (value < val) return contains(root->left, value);
return contains(root->right, value);
}
// Erzeugt ein Array von len Zahlen zwischen 1 und 2*len, alle einzigartig,
// außer eine Zahl wird dupliziert.
unsigned int *createNumbers(unsigned int len) {
if (len == 0) return NULL;
unsigned int *numbers = malloc(len * sizeof(unsigned int));
if (!numbers) return NULL;
TreeNode *tree = NULL;
srand((unsigned int)time(NULL));
for (unsigned int i = 0; i < len - 1; i++) { // alle außer die Duplikate
unsigned int value;
do {
value = rand() % (2 * len) + 1;
} while (contains(tree, value));
int isDup = 0;
tree = addToTree(tree, &value, sizeof(value), compareInt, &isDup);
numbers[i] = value;
}
// Dupliziere zufällig eine Zahl
unsigned int dupIndex = rand() % (len - 1);
numbers[len - 1] = numbers[dupIndex];
// Speicher freigeben
clearTree(tree);
return numbers;
}
// Sortiert das Array und findet die einzige doppelte Zahl
unsigned int getDuplicate(const unsigned int *numbers, unsigned int len) {
if (!numbers || len < 2) return 0;
// Kopiere Array, da wir sortieren müssen
unsigned int *copy = malloc(len * sizeof(unsigned int));
if (!copy) return 0;
memcpy(copy, numbers, len * sizeof(unsigned int));
// qsort verwenden
qsort(copy, len, sizeof(unsigned int), compareUnsigned);
// Durchlauf und Nachbarn vergleichen
unsigned int dup = 0;
for (unsigned int i = 1; i < len; i++) {
if (copy[i] == copy[i - 1]) {
dup = copy[i];
break;
}
}
free(copy);
return dup;
}

BIN
numbers.o Normal file

Binary file not shown.

45
stack.c
View File

@ -1,33 +1,38 @@
#include <stdlib.h>
#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 onto the stack and returns new stack top
StackNode *push(StackNode *stack, void *data) {
StackNode *node = malloc(sizeof(StackNode));
if (!node) return stack; // allocation failed → leave stack unchanged
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data)
{
node->data = data;
node->next = stack;
return node; // new top
}
// 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)
{
// Removes the top element, frees node (NOT data), returns new top
StackNode *pop(StackNode *stack) {
if (stack == NULL) return NULL;
StackNode *next = stack->next;
free(stack);
return next; // new top
}
// Returns the data of the top element.
void *top(StackNode *stack)
{
// Returns data of top node or NULL
void *top(StackNode *stack) {
if (!stack) return NULL;
return stack->data;
}
// Clears stack and releases all memory.
void clearStack(StackNode *stack)
{
// Frees entire stack (NOT data!)
void clearStack(StackNode *stack) {
while (stack != NULL) {
StackNode *next = stack->next;
free(stack);
stack = next;
}
}

10
stack.h
View File

@ -7,13 +7,17 @@ The latest element is taken from the stack. */
#include <stdlib.h>
//TODO: passenden Datentyp als struct anlegen
// passenden Datentyp als struct anlegen
typedef struct StackNode {
void *data; // Zeiger auf beliebige Daten
struct StackNode *next; // Zeiger auf das nächste Element im Stack
} StackNode;
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data);
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
// freed by caller.)
// 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);
// Returns the data of the top element.

BIN
stack.o Normal file

Binary file not shown.

49
test_numbers.c Normal file
View File

@ -0,0 +1,49 @@
#include <stdio.h>
#include <stdlib.h>
#include "numbers.h"
int main(void)
{
printf("=== TEST: createNumbers & getDuplicate ===\n");
unsigned int len = 20;
unsigned int *arr = createNumbers(len);
if (!arr)
{
printf("FAILED: createNumbers returned NULL\n");
return 1;
}
printf("Array created: ");
for (unsigned int i = 0; i < len; i++)
printf("%u ", arr[i]);
printf("\n");
unsigned int dup = getDuplicate(arr, len);
if (dup == 0)
{
printf("FAILED: getDuplicate returned 0 (no duplicate found)\n");
free(arr);
return 1;
}
// Count occurrences manually as safety check
unsigned int count = 0;
for (unsigned int i = 0; i < len; i++)
if (arr[i] == dup)
count++;
if (count != 2)
{
printf("FAILED: duplicate=%u occurs %u times (expected 2)\n", dup, count);
free(arr);
return 1;
}
printf("SUCCESS: duplicate number is %u and appears exactly twice.\n", dup);
free(arr);
return 0;
}

BIN
test_numbers.exe Normal file

Binary file not shown.

41
test_stack.c Normal file
View File

@ -0,0 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main() {
StackNode *stack = NULL;
// Einige Integer dynamisch alloziieren
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
int *c = malloc(sizeof(int));
*a = 10; *b = 20; *c = 30;
stack = push(stack, a);
stack = push(stack, b);
stack = push(stack, c);
// Test top()
printf("Top = %d (expected 30)\n", *(int *)top(stack));
// pop()
stack = pop(stack); // removed 30
free(c); // data gehört Benutzer!
printf("Top = %d (expected 20)\n", *(int *)top(stack));
stack = pop(stack); free(b); // removed 20
stack = pop(stack); free(a); // removed 10
// stack should now be empty
if (stack == NULL) {
printf("Stack empty ok\n");
} else {
printf("Error: stack not empty!\n");
}
// Cleanup just in case
clearStack(stack);
return 0;
}

BIN
test_stack.exe Normal file

Binary file not shown.

BIN
timer.o Normal file

Binary file not shown.