19 Commits
Author SHA1 Message Date
silvana884 dcdc1949ab Noch ein paar Kommentare zum binTree 2025-12-12 06:49:18 +01:00
haemmerlre98889 f513d63ebf Kommentare angepasst 2025-12-11 15:47:51 +01:00
silvana884 f249355a30 Noch ein bisschen kommentiert 2025-12-11 10:00:44 +01:00
silvana884 8f3ee7b9d7 Fertig 2025-12-11 09:46:50 +01:00
silvana884 37f38cbc7d Numbers Test erfolgreich ebstanden 2025-12-11 09:15:03 +01:00
silvana884 dcc90edfa3 Pias Teil uerbenommen 2025-12-11 08:58:19 +01:00
silvana884 63e7c18db6 Alle geschriebenen Tests bestanden 2025-12-10 19:57:47 +01:00
silvana884 2c35bafba9 Tests fuer den BinaryTree geschrieben, makefile ergaenzt 2025-12-10 19:15:09 +01:00
silvana884 bc24ca7b46 Testkopefe geschrieben 2025-12-10 10:47:57 +01:00
silvana884 b3c9fec7ba Datentyp fuer Strukturvariable data auf void geandert 2025-12-10 10:04:13 +01:00
silvana884 c860a197ee createNumbers FUnktion implementiert 2025-12-05 10:34:11 +01:00
silvana884 bfcb9ed426 Fehler bei clearStack verbessert, erste Implementation von numbers.c 2025-12-05 08:45:25 +01:00
silvana884 5859268475 Funktionen des Binaerbaums implementiert 2025-12-04 11:40:26 +01:00
silvana884 be5c1754f9 NextTreeData erster versuch 2025-12-03 22:07:13 +01:00
silvana884 7a20acd8f6 Grundlegende Stack-funktionen implementiert und Struct nochmal ueberarbeitet 2025-12-03 14:15:45 +01:00
silvana884 09db456716 Top Funktion des Stacks implementiert 2025-12-03 13:59:24 +01:00
silvana884 fc5f249554 StackNode strcut definiert 2025-12-03 11:13:06 +01:00
silvana884 1536413888 treeSize implementiert 2025-12-03 10:52:50 +01:00
silvana884 c06f7c2b61 cleaTree und addToTree hinzugefuegt 2025-12-03 10:36:33 +01:00
26 changed files with 510 additions and 41 deletions
+145
View File
@@ -0,0 +1,145 @@
#include "unity.h"
#include <stdlib.h>
#include "bintree.h"
static int compare(const void *a, const void *b)
{
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b); // a und b werden in int konvertiert und deren Werte miteinander verglichen
// returns 1 for a>b or -1 for a<b
// in bintree.c wird ueberprueft, ob compare eine positive oder eine negative Zahl zurueckgibt,
// wenn a groeßer b, positiv und dann wird links nach Teilbauemen gesucht
}
void setUp() {}
void tearDown() {}
//Adds a single element to the tree
void test_add_single_element_to_Tree()
{
TreeNode *root = NULL;
int value = 5;
int duplicate = -1;
root = addToTree(root, &value, sizeof(int), compare, &duplicate);
TEST_ASSERT_NOT_NULL(root); //uberprueft, ob root dem Tree hinzugefuegt werden konnte
TEST_ASSERT_EQUAL_INT(5, *(int*)root->data); //ueberprueft, ob der Wert fuer data richtig uebernommen wurde
TEST_ASSERT_EQUAL_INT(0, duplicate); //ueberprueft, ob isDuplicate 0 gesetzt wurde (neue Knoten -> isDuplicate sollte 0 sein)
clearTree(root);
}
//Adds multiplie elements to a tree
void test_add_multiple_elements_to_Tree()
{
TreeNode *root = NULL;
int value[] = {2, 5, 7, 9};
int duplicate = -1;
for(int j = 0; j < 4; ++j)
{
root = addToTree(root, &value[j], sizeof(int), compare, &duplicate); //Duplikate nicht erlaubt
}
TEST_ASSERT_EQUAL_INT(4, treeSize(root));
clearTree(root);
}
//Detects the size of a tree
void test_detect_empty_size()
{
TEST_ASSERT_EQUAL_INT(0, treeSize(NULL));
}
//checks, wether size of tree is correctly determined and wether clearTree() works
// Test: Duplikate nicht erlaubt (isDuplicate != NULL)
void test_detect_size() {
TreeNode *root = NULL;
int values[] = {1, 3, 1, 4, 5, 6, 7, 5, 9, 10};
int duplicate = 0; // wird pro Einfügen gesetzt
for (int j = 0; j < 10; ++j) {
root = addToTree(root, &values[j], sizeof(int), compare, &duplicate);
if (duplicate) {
// Ist der Wert schon eingefuegt? Also gibt es schon ein Duplikat?
TEST_ASSERT_TRUE(duplicate == 1);
}
duplicate = 0; // zurücksetzen für nächstes Einfügen
}
// Prüfen der Baumgroeße ohne Duplikate
TEST_ASSERT_EQUAL_INT(8, treeSize(root));
clearTree(root);
}
// Test: Duplikate erlaubt (isDuplicate == NULL)
void test_add_multiplie_elements_one_dup() {
TreeNode *root = NULL;
int values[] = {1, 3, 1, 4, 5, 6, 7, 5, 9, 10};
for (int j = 0; j < 10; ++j) {
root = addToTree(root, &values[j], sizeof(int), compare, NULL);
}
// Alle Werte inklusive Duplikate
TEST_ASSERT_EQUAL_INT(10, treeSize(root));
clearTree(root);
}
// Hilfsfunktion: rekursive Inorder-Prüfung
void inorderCheck(TreeNode *node, int expected[], int *idx) {
if (node == NULL) return;
// Linken Teilbaum prüfen
inorderCheck(node->left, expected, idx);
// Aktuelles Element prüfen -> wenn das aktuelle Element gefunden wurde, wird naechstes gesucht
TEST_ASSERT_EQUAL_INT(expected[*idx], *(int*)node->data);
(*idx)++;
// Rechten Teilbaum prüfen
inorderCheck(node->right, expected, idx);
}
//Traverses the tree inorder to check wether nextTreeData works
void test_inorder() {
TreeNode *root = NULL;
int values[] = {5, 3, 7, 2, 4, 6, 8};
// Baum füllen
for (int i = 0; i < 7; i++) {
root = addToTree(root, &values[i], sizeof(int), compare, NULL);
}
// Erwartete Inorder-Reihenfolge
int expected[] = {2,3,4,5,6,7,8};
int idx = 0;
//rekursives Pruefen der Eintraege
inorderCheck(root, expected, &idx);
// Alle Einträge geprüft?
TEST_ASSERT_EQUAL_INT(7, idx);
clearTree(root);
}
int main()
{
UNITY_BEGIN();
RUN_TEST(test_add_single_element_to_Tree);
RUN_TEST(test_add_multiple_elements_to_Tree);
RUN_TEST(test_add_multiplie_elements_one_dup);
RUN_TEST(test_detect_empty_size);
RUN_TEST(test_detect_size);
RUN_TEST(test_inorder);
return UNITY_END();
}
+97
View File
@@ -12,7 +12,53 @@
// 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(data!= NULL && dataSize > 0)
{
if(root == NULL) //Abbruchbedingung: Keine Wurzel vorhanden, deshalb fuegen wir hier einen neuen Knote ein
{
TreeNode *newNode = (TreeNode *)malloc(sizeof(TreeNode));
if(newNode == NULL)
{
return NULL;
}
newNode->data = malloc(dataSize);
if(newNode->data == NULL)
{
free(newNode);
return NULL;
}
memcpy(newNode->data, data, dataSize);
newNode->left = NULL;
newNode->right = NULL;
if(isDuplicate!= NULL) //wenn isDuplicate ungelich null, ignoriere duplikate und setze isDuplaicate 0 fuer neues Element
{
*isDuplicate = 0;
}
return newNode;
}
int cmp = compareFct(root->data, 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
{
if (isDuplicate) { //Duplikate sollen ignoriert werden
*isDuplicate = 1;
}
else {
// isDuplicate == NULL → trotzdem ein Duplikat einfügen (z.B. rechts)
root->right = addToTree(root->right, data, dataSize, compareFct, NULL);
}
}
return root;
}
return NULL;
}
// 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 +66,68 @@ 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 *stack = NULL;
// 1) Falls neuer Baum übergeben wurde → Initialisieren
if (root != NULL)
{
// alten Stack leeren
while (stack != NULL)
stack = pop(stack);
// alle linken Knoten pushen
while (root != NULL) {
stack = push(stack, root);
root = root->left;
}
}
// 2) Wenn Stack leer → fertig
if (stack == NULL)
return NULL;
// 3) Top-Knoten holen
TreeNode *node = (TreeNode *)top(stack);
stack = pop(stack);
// 4) Wenn rechter Teilbaum existiert → alle linken Knoten pushen
TreeNode *right = node->right;
while (right != NULL) {
stack = push(stack, right);
right = right->left;
}
// 5) Daten zurückgeben
return node->data;
}
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root)
{
if (root == NULL)
{
return;
}
// Erst linken Knoten löschen
clearTree(root->left);
// Dann rechten Knoten löschen
clearTree(root->right);
// Dann eigenen Speicher freigeben
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); //1, weil eine Wurzel gefunden wurde und dann immer plus eins fuer einen Teilbaum
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+4
View File
@@ -1 +1,5 @@
Silvana;9944
hannes;9910
silvana;9865
player2;4983
player1;3999
BIN
View File
Binary file not shown.
+44 -27
View File
@@ -1,49 +1,66 @@
CC = gcc
FLAGS = -g -Wall -lm
ifeq ($(OS),Windows_NT)
include makefile_windows.variables
else
UNAME = $(shell uname)
ifeq ($(UNAME),Linux)
include makefile_linux.variables
else
include makefile_mac.variables
endif
endif
raylibfolder = ./raylib
unityfolder = ./unity
FLAGS = -g -Wall -I$(unityfolder)
ifeq ($(OS),Windows_NT)
include makefile_windows.variables
else
UNAME := $(shell uname)
ifeq ($(UNAME),Linux)
include makefile_linux.variables
else
include makefile_mac.variables
endif
endif
# --------------------------
# Initiales Programm bauen (zum ausprobieren)
# Objektdateien
# --------------------------
program_obj_files := stack.o bintree.o numbers.o timer.o highscore.o
%.o: %.c
$(CC) $(FLAGS) -c $< -o $@
doble: main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble
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
$(program_obj_filesobj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@
# --------------------------
# Unit Tests
# --------------------------
unitTests:
echo "needs to be implemented"
@echo "needs to be implemented"
binTreeTest: stack.o bintree.o binTreeTest.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -o runbinTreeTest binTreeTest.c bintree.o stack.o $(unityfolder)/unity.c
test_numbers: numbers_no_tree.o bintree.o stack.o test_numbers.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -o run_numbersTests test_numbers.c numbers_no_tree.o bintree.o stack.o $(unityfolder)/unity.c
test_stack: stack.o test_stack.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -o runstackTests test_stack.c stack.o $(unityfolder)/unity.c
# --------------------------
# Clean
# Cleaning
# --------------------------
clean:
ifeq ($(OS),Windows_NT)
del /f *.o doble
del /f *.o doble runstackTests run_numbersTests runbintreeTests
else
rm -f *.o doble
rm -f *.o doble runstackTests run_numbersTests runbintreeTests
endif
+104
View File
@@ -0,0 +1,104 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#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.
// Returns len random numbers between 1 and 2*len in random order,
// all different, except for exactly one duplicate (two entries the same).
// Uses your binary search tree implementation to check for duplicates while generating numbers.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "numbers.h"
#include "bintree.h"
int compareFct(const void *a, const void *b)
{
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b); // a und b werden in int konvertiert und deren Werte miteinander verglichen
// returns 1 for a>b or -1 for a<b
// in bintree.c wird ueberprueft, ob compare eine positive oder eine negative Zahl zurueckgibt,
// wenn a groeßer b, positiv und dann wird links nach Teilbauemen gesucht
}
// Erzeugt len Zufallszahlen zwischen 1 und 2*len
// alle einzigartig, außer genau ein Duplikat
unsigned int *createNumbers(unsigned int len)
{
if (len < 2)
return NULL;
srand((unsigned int)time(NULL));
unsigned int *numbers = malloc(len * sizeof(unsigned int));
if (!numbers)
return NULL;
TreeNode *root = NULL; // Baum anfänglich leer
unsigned int count = 0;
// Zufallszahlen generieren, bis das Array voll ist
while (count < len)
{
unsigned int random = (rand() % (2 * len)) + 1;
int duplicate = 0; // Anfangswert für Duplikat-Check
root = addToTree(root, &random, sizeof(random), compareFct, &duplicate);
if (root == NULL)
{
free(numbers);
return NULL;
}
if (!duplicate)
{
numbers[count++] = random;
}
// duplicate == 1 → Zahl existiert schon, neue Zahl generieren
}
// genau ein Duplikat erzeugen
unsigned int idx1 = rand() % len;
unsigned int idx2 = rand() % len;
while (idx2 == idx1)
idx2 = rand() % len;
numbers[idx2] = numbers[idx1];
// Baum wieder freigeben
clearTree(root);
return numbers;
}
// findet die eine doppelte Zahl im Array
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
{
if (!numbers || len < 2)
return 0;
for (unsigned int i = 0; i < len; i++)
{
for (unsigned int j = i + 1; j < len; j++)
{
if (numbers[i] == numbers[j])
return numbers[i];
}
}
return 0;
}
+2
View File
@@ -1,6 +1,8 @@
#ifndef NUMBERS_H
#define NUMBERS_H
int compareFct(const void *a, const void *b);
// 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.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+31 -9
View File
@@ -1,33 +1,55 @@
#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 as pointer onto the stack.
StackNode *push(StackNode *stack, void *data)
{
if (!data)
{
return stack; //Nichts pushen
}
StackNode *t = (StackNode *)malloc(sizeof(StackNode));
if(!t)
{
return NULL; //Speicherfehler
}
t->next = stack;
t->data = data;
return t; //Gibt den ersten StackNode des Stacks zurueck
return NULL;
}
// 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;
}
return stack->next;
}
// Returns the data of the top element.
void *top(StackNode *stack)
{
if(stack)
{
return stack->data;
}
return NULL;
}
// Clears stack and releases all memory.
void clearStack(StackNode *stack)
{
while(stack)
{
StackNode *tmp = stack; //merkt sich den momentanen obersten Knoten
stack = stack->next; //setzt den obersten Knoten auf den Zweiten im Stack
free(tmp->data);
free(tmp);
}
}
+5
View File
@@ -8,6 +8,11 @@ The latest element is taken from the stack. */
#include <stdlib.h>
//TODO: passenden Datentyp als struct anlegen
typedef struct Node{
void* data;
struct Node *next;
}StackNode;
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data);
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1
View File
@@ -150,3 +150,4 @@ int main(void)
return UNITY_END();
}
BIN
View File
Binary file not shown.
+72
View File
@@ -0,0 +1,72 @@
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
//Testfunkionen zu push, pull, top & clearStack schreiben
void setUp()
{
}
void tearDown()
{
}
void test(char *name, int condition) {
if (condition) {
printf("[OK] %s\n", name);
} else {
printf("[FAIL] %s\n", name);
}
}
int main() {
StackNode *stack = NULL;
// Werte dynamisch anlegen
int *val1 = malloc(sizeof(int));
*val1 = 5;
stack = push(stack, val1);
test("push(5) legt 5 oben auf den Stack", *(int*)stack->data == 5);
int *val2 = malloc(sizeof(int));
*val2 = 6;
stack = push(stack, val2);
test("push(6) legt 6 oben auf den Stack", *(int*)stack->data == 6);
int *val3 = malloc(sizeof(int));
*val3 = 24;
stack = push(stack, val3);
test("push(24) legt 24 oben auf den Stack", *(int*)stack->data == 24);
// Test top()
int t = *(int*)top(stack);
test("top() liefert 24", t == 24);
// Test pop()
StackNode *tmp;
tmp = stack;
stack = pop(stack);
free(tmp->data); // Daten freigeben
free(tmp); // Knoten freigeben
test("pop() entfernt 24, 6 ist jetzt oben", *(int*)stack->data == 6);
tmp = stack;
stack = pop(stack);
free(tmp->data);
free(tmp);
test("pop() entfernt 6, 5 ist jetzt oben", *(int*)stack->data == 5);
tmp = stack;
stack = pop(stack);
free(tmp->data);
free(tmp);
test("pop() entfernt 5, Stack ist jetzt leer", stack == NULL);
// Am Ende Stack leeren (falls noch Elemente übrig)
clearStack(stack);
return 0;
}
BIN
View File
Binary file not shown.