Stackfunktionen

This commit is contained in:
Bannach 2025-12-02 17:42:33 +01:00
parent c62a282234
commit 7ee5ad0b36
8 changed files with 73 additions and 72 deletions

View File

@ -8,6 +8,7 @@
* `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. */
static StackNode *stack = NULL;
TreeNode* createNode(const void *data, size_t dataSize) { TreeNode* createNode(const void *data, size_t dataSize) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
@ -34,36 +35,31 @@
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). // 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 *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{ {
TreeNode *newNode = createNode(data,dataSize);
if (root == NULL) if (root == NULL)
{ if (isDuplicate!=NULL) { {
TreeNode *newNode = createNode(data,dataSize);
if (isDuplicate)
*isDuplicate = 0; *isDuplicate = 0;
}
return newNode; return newNode;
} }
if (compareFct(root->data, newNode->data)==0) if (compareFct(root->data, data)==0)
{ {
if (isDuplicate==NULL) { if (isDuplicate != NULL) {
free(newNode);
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else
{
free(newNode->data);
free(newNode);
*isDuplicate=1; *isDuplicate=1;
return root; return root;
} }
TreeNode *newNode = createNode(data,dataSize);
return newNode;
} }
else if (compareFct(root->data, newNode->data)>0) else if (compareFct(root->data, data)>0)
{ {
free(newNode);
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
} }
else if (compareFct(root->data, newNode -> data)<0) else if (compareFct(root->data, data)<0)
{ {
free(newNode);
root->right= addToTree(root->right, data, dataSize, compareFct, isDuplicate); root->right= addToTree(root->right, data, dataSize, compareFct, isDuplicate);
} }
return root; return root;
@ -75,6 +71,15 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc
void *nextTreeData(TreeNode *root) void *nextTreeData(TreeNode *root)
{ {
if (root != NULL) {
clearStack(stack);
stack = NULL;
}
while (root != NULL)
{
stack = push(stack, root->data);
root = root->left;
}
} }
// Releases all memory resources (including data copies). // Releases all memory resources (including data copies).

View File

@ -1,3 +1,5 @@
player_name;18989 player_name;18989
test;9905
player_name;4983 player_name;4983
highscores.txt;4979
player1;3999 player1;3999

View File

@ -35,15 +35,14 @@ $(program_obj_filesobj_files): %.o: %.c
# -------------------------- # --------------------------
# Unit Tests # Unit Tests
# -------------------------- # --------------------------
unitTests: stackTests: stack.o test_stack.c $(unity_strc)
echo "needs to be implemented" $(CC) $(CFLAGS) $(LDFLAGS) -I$(unityfolder) $^ -o runStackTests
# -------------------------- # --------------------------
# Clean # Clean
# -------------------------- # --------------------------
clean: clean:
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
del /f *.o doble del /f *.o doble doble_initial runStackTests
else else
rm -f *.o doble rm -f *.o doble doble_initial runStackTests
endif endif

View File

@ -10,13 +10,35 @@
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen. * 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. */
int compareFct(const void *a, const void *b)
{
return *(int*)a - *(int*)b;
}
// 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 different, except for two entries.
// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while // Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while
// creating random numbers. // creating random numbers.
unsigned int *createNumbers(unsigned int len) unsigned int *createNumbers(unsigned int len)
{
TreeNode *root = NULL;
unsigned int* numbers = malloc(len * sizeof(unsigned int));
srand(time(NULL));
while(treeSize(root)<len)
{
unsigned int zahl = rand()%(2*len-1)+1;
addToTree(root, &zahl, sizeof(zahl),compareFct,0);
}
nextTreeData(root);
for(int i=0;i<len;i++)
{ {
nextTreeData(NULL);
}
unsigned int duplicate = rand()%(len-1)+1;
return numbers;
} }
// Returns only the only number in numbers which is present twice. Returns zero on errors. // Returns only the only number in numbers which is present twice. Returns zero on errors.

BIN
runStackTests.exe Normal file

Binary file not shown.

63
stack.c
View File

@ -11,66 +11,39 @@
StackNode *push(StackNode *stack, void *data) StackNode *push(StackNode *stack, void *data)
{ {
// 1. Einen neuen StackNode erstellen
StackNode *newNode = (StackNode *)malloc(sizeof(StackNode));
// Überprüfen, ob die Speicherreservierung erfolgreich war
if (newNode == NULL)
{
// Wenn malloc fehlschlägt, geben wir NULL zurück, um einen Fehler anzuzeigen.
return NULL;
}
// 2. Die Daten in den neuen Knoten legen
newNode->data = data;
// 3. Den 'next'-Zeiger des neuen Knotens auf den aktuellen Stack-Top setzen
// Der neue Knoten zeigt nun auf das Element, das zuvor ganz oben war.
newNode->next = stack;
// 4. Den neuen Knoten als neuen Stack-Top zurückgeben
// Er ist jetzt das oberste Element.
return newNode;
} }
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be // Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
// freed by caller.) // freed by caller.)
StackNode *pop(StackNode *stack) StackNode *pop(StackNode *stack)
{ {
// 1. Überprüfen, ob der Stack leer ist
if (stack == NULL)
{
// Wenn der Stack leer ist, gibt es nichts zu entfernen.
// Wir geben NULL zurück, da der Stack immer noch leer ist.
return NULL;
}
// 2. Einen Zeiger auf das aktuelle oberste Element speichern
// Dieses Element wollen wir entfernen und dessen Speicher freigeben.
StackNode *oldTop = stack;
// 3. Den Stack-Zeiger auf das nächste Element im Stack setzen
// Das Element, das unter dem alten Top lag, wird jetzt zum neuen Top.
StackNode *newTop = stack->next;
// 4. Den Speicher des alten obersten Elements freigeben
// Wichtig: Die Daten, auf die oldTop->data zeigt, werden hier NICHT freigegeben.
// Das muss, wie in der .h-Datei beschrieben, vom Aufrufer erledigt werden,
// falls die Daten dynamisch alloziert wurden.
free(oldTop);
// 5. Den neuen Stack-Top zurückgeben
return newTop;
} }
// Returns the data of the top element. // Returns the data of the top element.
void *top(StackNode *stack) void *top(StackNode *stack)
{ {
if (stack == NULL)
{
return;
}
else
{
return stack->data;
}
} }
// Clears stack and releases all memory. // Clears stack and releases all memory.
void clearStack(StackNode *stack) void clearStack(StackNode *stack)
{ {
StackNode *head = stack;
StackNode *current = head;
while(current)
{
free(current->data);
StackNode *nextNode = current->next;
free(current);
current = nextNode;
}
head = NULL;
} }

BIN
stack.o Normal file

Binary file not shown.

View File

@ -48,7 +48,7 @@ void test_push_single_element() {
stack = push(stack, data1); stack = push(stack, data1);
assert_equals_ptr(data1, top(stack), "Top should be 10"); assert_equals_ptr(data1, stack->data, "Top should be 10");
assert_equals_ptr(NULL, stack->next, "Next element should be NULL"); assert_equals_ptr(NULL, stack->next, "Next element should be NULL");
// Aufräumen // Aufräumen
@ -67,7 +67,7 @@ void test_push_multiple_elements() {
stack = push(stack, data2); // Stack: [20, 10] stack = push(stack, data2); // Stack: [20, 10]
stack = push(stack, data3); // Stack: [30, 20, 10] stack = push(stack, data3); // Stack: [30, 20, 10]
assert_equals_int(30, *(int*)top(stack), "Top should be 30"); assert_equals_int(30, *(int*)stack->data, "Top should be 30");
assert_equals_int(20, *(int*)stack->next->data, "Second element should be 20"); assert_equals_int(20, *(int*)stack->next->data, "Second element should be 20");
assert_equals_int(10, *(int*)stack->next->next->data, "Third element should be 10"); assert_equals_int(10, *(int*)stack->next->next->data, "Third element should be 10");
assert_equals_ptr(NULL, stack->next->next->next, "Fourth element should be NULL"); assert_equals_ptr(NULL, stack->next->next->next, "Fourth element should be NULL");
@ -91,14 +91,14 @@ void test_pop_single_element() {
int *data1 = (int *)malloc(sizeof(int)); *data1 = 10; int *data1 = (int *)malloc(sizeof(int)); *data1 = 10;
stack = push(stack, data1); // Stack: [10] stack = push(stack, data1); // Stack: [10]
assert_equals_int(10, *(int*)top(stack), "Top should be 10 before pop"); assert_equals_int(10, *(int*)stack->data, "Top should be 10 before pop");
// Daten freigeben, bevor der Knoten freigegeben wird // Daten freigeben, bevor der Knoten freigegeben wird
free(top(stack)); // Freigabe von data1 free(top(stack)); // Freigabe von data1
stack = pop(stack); // Stack: [] stack = pop(stack); // Stack: []
assert_equals_ptr(NULL, stack, "Stack should be empty after popping last element"); assert_equals_ptr(NULL, stack, "Stack should be empty after popping last element");
assert_equals_ptr(NULL, top(stack), "Top should be NULL after popping last element"); assert_equals_ptr(NULL, stack->data, "Top should be NULL after popping last element");
} }
void test_pop_multiple_elements() { void test_pop_multiple_elements() {