erste version

This commit is contained in:
Kristin 2025-12-07 18:35:22 +01:00
parent 55532cbb42
commit 68563ec297
7 changed files with 373 additions and 46 deletions

100
bintree.c
View File

@ -1,6 +1,6 @@
#include <string.h>
#include "stack.h"
#include "bintree.h" #include "bintree.h"
#include "stack.h"
#include <string.h>
// TODO: binären Suchbaum implementieren // TODO: binären Suchbaum implementieren
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), /* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
@ -8,29 +8,99 @@
* `treeSize`: zählt die Knoten im Baum (rekursiv), * `treeSize`: zählt die Knoten im Baum (rekursiv),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ * `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 // typedef int (*CompareFctType)(const void *arg1, const void *arg2);
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). // Adds a copy of data's pointer destination to the tree using compareFct for
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) // 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) {
if (isDuplicate) {
*isDuplicate = 0;
} }
// 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. if (root == NULL) {
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, TreeNode *node = malloc(sizeof(TreeNode));
// push the top node and push all its left nodes. node->data = malloc(dataSize);
void *nextTreeData(TreeNode *root) memcpy(node->data, data, dataSize);
{ node->left = NULL;
node->right = NULL;
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 {
// Duplikat
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. 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) {
static StackNode *stack = NULL;
// Neue Iteration starten
if (root != NULL) {
clearStack(&stack);
TreeNode *curr = root;
// Alle linken Kinder pushen
while (curr != NULL) {
stack = push(stack, curr);
curr = curr->left;
}
}
// Wenn leer → fertig
if (stack == NULL)
return NULL;
// Oberstes Element lesen
TreeNode *node = (TreeNode *)stack->data;
stack = pop(stack);
// Jetzt den rechten Teilbaum verarbeiten
TreeNode *curr = node->right;
while (curr != NULL) {
stack = push(stack, curr);
curr = curr->left;
}
return node->data;
} }
// Releases all memory resources (including data copies). // Releases all memory resources (including data copies).
void clearTree(TreeNode *root) 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. // 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 == NULL)
return 0;
return 1 + treeSize(root->left) + treeSize(root->right);
} }

View File

@ -1,2 +1,5 @@
krisp;4986 krisp;4986
krisp;4985
Kristin;4972
player1;3999 player1;3999
krisp;3991

View File

@ -36,16 +36,39 @@ $(program_obj_files): %.o: %.c
# Unit Tests # Unit Tests
# -------------------------- # --------------------------
TEST_BIN = runTests STACK_TEST_BIN = runStackTests
NUMBERS_TEST_BIN = runNumbersTests
BINARY_TEST_BIN = runBinaryTests
unitTests: stack.o test_stack.o # --- Stack Tests ---
$(CC) $(FLAGS) -I$(unityfolder) -o $(TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c stackTests: stack.o test_stack.o
$(CC) $(FLAGS) -I$(unityfolder) -o $(STACK_TEST_BIN) \
stack.o test_stack.o $(unityfolder)/unity.c
test_stack.o: test_stack.c test_stack.o: test_stack.c
$(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o $(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o
# --- Numbers Tests ---
numbersTests: numbers.o bintree.o stack.o test_numbers.o
$(CC) $(FLAGS) -I$(unityfolder) -o $(NUMBERS_TEST_BIN) \
numbers.o bintree.o stack.o test_numbers.o $(unityfolder)/unity.c
test_numbers.o: test_numbers.c
$(CC) $(FLAGS) -I$(unityfolder) -c test_numbers.c -o test_numbers.o
# --- Binary Tree Tests ---
binaryTests: bintree.o stack.o test_binary.o
$(CC) $(FLAGS) -I$(unityfolder) -o $(BINARY_TEST_BIN) \
bintree.o stack.o test_binary.o $(unityfolder)/unity.c
test_binary.o: test_binary.c
$(CC) $(FLAGS) -I$(unityfolder) -c test_binary.c -o test_binary.o
# -------------------------- # --------------------------
# Clean # Clean
# -------------------------- # --------------------------
clean: clean:
rm -f *.o doble rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN)

View File

@ -1,26 +1,91 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "numbers.h" #include "numbers.h"
#include "bintree.h" #include "bintree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int compareUnsignedInt(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;
}
// TODO: getDuplicate und createNumbers implementieren // TODO: getDuplicate und createNumbers implementieren
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. /**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen. * Zufallszahlen. Sicherstellen, dass beim Befüllen keine Duplikate entstehen.
* Duplizieren eines zufälligen Eintrags im Array. * Duplizieren eines zufälligen Eintrags im Array.
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ * 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 len random numbers between 1 and 2x len in random order which are all
// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while // different, except for two entries. Returns NULL on errors. Use your
// creating random numbers. // implementation of the binary search tree to check for possible duplicates
unsigned int *createNumbers(unsigned int len) // while creating random numbers.
{ unsigned int *createNumbers(unsigned int len) {
if (len < 2)
return NULL;
unsigned int *arr = malloc(sizeof(unsigned int) * len);
if (!arr)
return NULL;
TreeNode *root = NULL;
srand((unsigned int)time(NULL));
for (unsigned int i = 0; i < len - 1; i++) {
unsigned int num;
int isDuplicate;
do {
num = (rand() % (2 * len)) + 1;
isDuplicate = 0;
root = addToTree(root, &num, sizeof(unsigned int), compareUnsignedInt,
&isDuplicate);
} while (isDuplicate); // nur akzeptieren, wenn eindeutig
arr[i] = num;
} }
// Returns only the only number in numbers which is present twice. Returns zero on errors. // Jetzt gezielt EIN Duplikat erzeugen
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) unsigned int duplicateIndex = rand() % (len - 1);
{ arr[len - 1] = arr[duplicateIndex];
clearTree(root);
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 || len < 2)
return 0;
unsigned int *copy = malloc(sizeof(unsigned int) * len);
if (!copy)
return 0;
memcpy(copy, numbers, sizeof(unsigned int) * len);
// Sortierung
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
// Duplikat finden: zwei gleiche nebeneinander
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++) {
if (copy[i] == copy[i + 1]) {
duplicate = copy[i];
break;
}
}
free(copy);
return duplicate;
} }

105
test_binary.c Normal file
View File

@ -0,0 +1,105 @@
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bintree.h"
int compareUnsignedInt(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;
}
TreeNode *root = NULL;
void setUp(void) {
root = NULL; // vor jedem Test leeren
}
void tearDown(void) { clearTree(root); }
// Test, ob addToTree Knoten korrekt hinzufügt
void test_addToTree_basic(void) {
int isDup;
unsigned int val = 10;
root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup);
TEST_ASSERT_NOT_NULL(root);
TEST_ASSERT_EQUAL_UINT(10, *(unsigned int *)root->data);
TEST_ASSERT_EQUAL_INT(0, isDup);
TEST_ASSERT_EQUAL_UINT(1, treeSize(root));
}
// Test, dass Duplikate erkannt werden
void test_addToTree_duplicate(void) {
int isDup;
unsigned int val1 = 10, val2 = 10;
root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, &isDup);
TEST_ASSERT_EQUAL_INT(0, isDup);
root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, &isDup);
TEST_ASSERT_EQUAL_INT(1, isDup);
TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); // Duplikate nicht hinzufügen
}
// Test nextTreeData Traversierung
void test_nextTreeData_in_order(void) {
unsigned int values[] = {20, 10, 30};
int isDup;
for (int i = 0; i < 3; i++) {
root = addToTree(root, &values[i], sizeof(values[i]), compareUnsignedInt,
&isDup);
}
unsigned int expected[] = {10, 20, 30};
int idx = 0;
void *data;
// **Neue Iteration starten**
data = nextTreeData(root);
while (data != NULL) {
TEST_ASSERT_EQUAL_UINT(expected[idx], *(unsigned int *)data);
idx++;
data = nextTreeData(NULL); // weitere Elemente abrufen
}
TEST_ASSERT_EQUAL_INT(3, idx); // alle 3 Knoten besucht
}
// Test clearTree gibt Speicher frei
void test_clearTree(void) {
unsigned int val = 42;
int isDup;
root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup);
clearTree(root);
root = NULL; // clearTree löscht nicht die root-Variable selbst
TEST_ASSERT_NULL(root);
}
// Test treeSize zählt korrekt
void test_treeSize(void) {
unsigned int vals[] = {10, 20, 5};
int isDup;
for (int i = 0; i < 3; i++) {
root =
addToTree(root, &vals[i], sizeof(vals[i]), compareUnsignedInt, &isDup);
}
TEST_ASSERT_EQUAL_UINT(3, treeSize(root));
}
int main(void) {
UNITY_BEGIN();
printf(
"\n------------------------binarytree test------------------------\n\n");
RUN_TEST(test_addToTree_basic);
RUN_TEST(test_addToTree_duplicate);
RUN_TEST(test_nextTreeData_in_order);
RUN_TEST(test_clearTree);
RUN_TEST(test_treeSize);
return UNITY_END();
}

61
test_numbers.c Normal file
View File

@ -0,0 +1,61 @@
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "numbers.h"
#define TEST_ARRAY_LEN 100
void test_createNumbers_length(void) {
unsigned int *arr = createNumbers(TEST_ARRAY_LEN);
TEST_ASSERT_NOT_NULL(arr);
free(arr);
}
void test_createNumbers_single_duplicate(void) {
unsigned int *arr = createNumbers(TEST_ARRAY_LEN);
TEST_ASSERT_NOT_NULL(arr);
unsigned int duplicate = getDuplicate(arr, TEST_ARRAY_LEN);
TEST_ASSERT_TRUE(duplicate > 0);
unsigned int count = 0;
for (unsigned int i = 0; i < TEST_ARRAY_LEN; i++) {
if (arr[i] == duplicate) {
count++;
}
}
TEST_ASSERT_EQUAL_UINT(2, count);
free(arr);
}
void test_getDuplicate_manual_array(void) {
unsigned int numbers[5] = {10, 20, 30, 40, 20};
unsigned int dup = getDuplicate(numbers, 5);
TEST_ASSERT_EQUAL_UINT(20, dup);
}
void test_getDuplicate_invalid_input(void) {
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(NULL, 5));
unsigned int arr[1] = {42};
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(arr, 1));
}
void setUp(void) {}
void tearDown(void) {}
int main(void) {
UNITY_BEGIN();
printf("\n------------------------numbers test------------------------\n\n");
RUN_TEST(test_createNumbers_length);
RUN_TEST(test_createNumbers_single_duplicate);
RUN_TEST(test_getDuplicate_manual_array);
RUN_TEST(test_getDuplicate_invalid_input);
return UNITY_END();
}

View File

@ -41,13 +41,13 @@ void test_deleteTopElement(void) {
stack = push(stack, &testInts[i]); stack = push(stack, &testInts[i]);
} }
TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack)); TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data);
stack = pop(stack); stack = pop(stack);
TEST_ASSERT_EQUAL_PTR(&testInts[1], top(stack)); TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data);
stack = pop(stack); stack = pop(stack);
TEST_ASSERT_EQUAL_PTR(&testInts[0], top(stack)); TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data);
stack = pop(stack); stack = pop(stack);
TEST_ASSERT_NULL(stack); TEST_ASSERT_NULL(stack);
@ -98,7 +98,7 @@ int main(void) {
UNITY_BEGIN(); UNITY_BEGIN();
printf("------------------------stack test------------------------\n"); printf("\n------------------------stack test------------------------\n\n");
RUN_TEST(test_createNode); RUN_TEST(test_createNode);
RUN_TEST(test_pushDataToStack); RUN_TEST(test_pushDataToStack);