Stackfunktionen
This commit is contained in:
parent
c62a282234
commit
7ee5ad0b36
37
bintree.c
37
bintree.c
@ -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).
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
9
makefile
9
makefile
@ -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
|
||||||
22
numbers.c
22
numbers.c
@ -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
BIN
runStackTests.exe
Normal file
Binary file not shown.
63
stack.c
63
stack.c
@ -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;
|
||||||
}
|
}
|
||||||
@ -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() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user