Stackfunktionen
This commit is contained in:
parent
c62a282234
commit
7ee5ad0b36
39
bintree.c
39
bintree.c
@ -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).
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
player_name;18989
|
||||
test;9905
|
||||
player_name;4983
|
||||
highscores.txt;4979
|
||||
player1;3999
|
||||
|
||||
9
makefile
9
makefile
@ -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
|
||||
22
numbers.c
22
numbers.c
@ -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
BIN
runStackTests.exe
Normal file
Binary file not shown.
65
stack.c
65
stack.c
@ -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;
|
||||
}
|
||||
@ -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() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user