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),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
static StackNode *stack = NULL;
TreeNode* createNode(const void *data, size_t dataSize) {
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).
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{
TreeNode *newNode = createNode(data,dataSize);
if (root == NULL)
{ if (isDuplicate!=NULL) {
*isDuplicate = 0;
}
{
TreeNode *newNode = createNode(data,dataSize);
if (isDuplicate)
*isDuplicate = 0;
return newNode;
}
if (compareFct(root->data, newNode->data)==0)
if (compareFct(root->data, data)==0)
{
if (isDuplicate==NULL) {
free(newNode);
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else
{
free(newNode->data);
free(newNode);
if (isDuplicate != NULL) {
*isDuplicate=1;
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);
}
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);
}
return root;
@ -75,6 +71,15 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc
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).

View File

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

View File

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

View File

@ -10,13 +10,35 @@
* 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. */
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 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)
{
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.

BIN
runStackTests.exe Normal file

Binary file not shown.

65
stack.c
View File

@ -11,66 +11,39 @@
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
// freed by caller.)
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.
void *top(StackNode *stack)
{
if (stack == NULL)
{
return;
}
else
{
return stack->data;
}
}
// Clears stack and releases all memory.
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);
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");
// Aufräumen
@ -67,7 +67,7 @@ void test_push_multiple_elements() {
stack = push(stack, data2); // Stack: [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(10, *(int*)stack->next->next->data, "Third element should be 10");
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;
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
free(top(stack)); // Freigabe von data1
stack = pop(stack); // Stack: []
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() {