Compare commits
5
Commits
43a953eaa6
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
526f1c3884 | ||
|
|
941374cbc2 | ||
|
|
9f0191845d | ||
|
|
d264a7513e | ||
|
|
2801e4b709 |
No files matched your search
@@ -10,27 +10,94 @@
|
|||||||
|
|
||||||
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
|
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
|
||||||
// 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) {
|
||||||
{
|
if (!root) {
|
||||||
|
// allocate new node
|
||||||
|
TreeNode *node = malloc(sizeof(TreeNode));
|
||||||
|
if (!node) return NULL;
|
||||||
|
|
||||||
|
node->data = malloc(dataSize);
|
||||||
|
if (!node->data) {
|
||||||
|
free(node);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(node->data, data, dataSize);
|
||||||
|
node->left = node->right = NULL;
|
||||||
|
|
||||||
|
if (isDuplicate) *isDuplicate = 0;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = compareFct(data, root->data);
|
||||||
|
|
||||||
|
if (cmp == 0) {
|
||||||
|
// duplicate
|
||||||
|
if (isDuplicate) *isDuplicate = 1;
|
||||||
|
return root; // do not insert duplicate
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp < 0)
|
||||||
|
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
|
||||||
|
else
|
||||||
|
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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.
|
// 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.
|
||||||
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element,
|
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element,
|
||||||
// push the top node and push all its left nodes.
|
// push the top node and push all its left nodes.
|
||||||
void *nextTreeData(TreeNode *root)
|
void *nextTreeData(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
static StackNode *stack = NULL;
|
||||||
|
|
||||||
|
// New tree → reset stack and push left path
|
||||||
|
if (root != NULL) {
|
||||||
|
clearStack(stack);
|
||||||
|
stack = NULL;
|
||||||
|
|
||||||
|
TreeNode *curr = root;
|
||||||
|
while (curr) {
|
||||||
|
stack = push(stack, curr);
|
||||||
|
curr = curr->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No tree / finished
|
||||||
|
if (!stack) return NULL;
|
||||||
|
|
||||||
|
// Top node
|
||||||
|
TreeNode *node = top(stack);
|
||||||
|
stack = pop(stack);
|
||||||
|
|
||||||
|
// After returning node, push its right subtree (all left nodes)
|
||||||
|
TreeNode *curr = node->right;
|
||||||
|
while (curr) {
|
||||||
|
stack = push(stack, curr);
|
||||||
|
curr = curr->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Releases all memory resources (including data copies).
|
// Releases all memory resources (including data copies).
|
||||||
void clearTree(TreeNode *root)
|
void clearTree(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (!root) return;
|
||||||
|
|
||||||
|
clearTree(root->left);
|
||||||
|
clearTree(root->right);
|
||||||
|
|
||||||
|
free(root->data);
|
||||||
|
free(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns the number of entries in the tree given by root.
|
// Returns the number of entries in the tree given by root.
|
||||||
unsigned int treeSize(const TreeNode *root)
|
unsigned int treeSize(const TreeNode *root)
|
||||||
{
|
{
|
||||||
|
if (!root) return 0;
|
||||||
|
return 1 + treeSize(root->left) + treeSize(root->right);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
kamte;2990
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
|
# --------------------------
|
||||||
|
# Compiler & Flags
|
||||||
|
# --------------------------
|
||||||
CC = gcc
|
CC = gcc
|
||||||
FLAGS = -g -Wall -lm
|
FLAGS = -g -Wall
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
include makefile_windows.variables
|
include makefile_windows.variables
|
||||||
|
RM = del /f
|
||||||
else
|
else
|
||||||
UNAME = $(shell uname)
|
UNAME = $(shell uname)
|
||||||
ifeq ($(UNAME),Linux)
|
ifeq ($(UNAME),Linux)
|
||||||
@@ -10,40 +14,49 @@ else
|
|||||||
else
|
else
|
||||||
include makefile_mac.variables
|
include makefile_mac.variables
|
||||||
endif
|
endif
|
||||||
|
RM = rm -f
|
||||||
endif
|
endif
|
||||||
|
|
||||||
raylibfolder = ./raylib
|
raylibfolder = ./raylib
|
||||||
unityfolder = ./unity
|
unityfolder = ./unity
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Initiales Programm bauen (zum ausprobieren)
|
# Objects du programme
|
||||||
|
# --------------------------
|
||||||
|
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
|
||||||
|
|
||||||
|
# --------------------------
|
||||||
|
# Cible principale
|
||||||
|
# --------------------------
|
||||||
|
doble : main.o $(program_obj_files)
|
||||||
|
$(CC) $(FLAGS) $^ -o $@
|
||||||
|
|
||||||
|
%.o : %.c
|
||||||
|
$(CC) $(FLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# --------------------------
|
||||||
|
# Programme initial
|
||||||
# --------------------------
|
# --------------------------
|
||||||
doble_initial:
|
doble_initial:
|
||||||
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Selbst implementiertes Programm bauen
|
# Tests unitaires
|
||||||
# --------------------------
|
# --------------------------
|
||||||
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
|
|
||||||
|
|
||||||
doble : main.o $(program_obj_files)
|
# Compile testStack.c en un exécutable testStack
|
||||||
$(CC) $(FLAGS) $^ -o doble
|
unitTests: testStack.o stack.o
|
||||||
|
$(CC) $(FLAGS) testStack.o stack.o -o testStack
|
||||||
|
@echo "----------------------------"
|
||||||
|
@echo "Running unit tests..."
|
||||||
|
./testStack
|
||||||
|
@echo "----------------------------"
|
||||||
|
|
||||||
$(program_obj_filesobj_files): %.o: %.c
|
testStack.o: testStack.c
|
||||||
$(CC) -c $(FLAGS) $^ -o $@
|
$(CC) $(FLAGS) -c testStack.c -o testStack.o
|
||||||
|
|
||||||
# --------------------------
|
|
||||||
# Unit Tests
|
|
||||||
# --------------------------
|
|
||||||
unitTests:
|
|
||||||
echo "needs to be implemented"
|
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Clean
|
# Clean
|
||||||
# --------------------------
|
# --------------------------
|
||||||
clean:
|
clean:
|
||||||
ifeq ($(OS),Windows_NT)
|
$(RM) *.o doble testStack doble_initial
|
||||||
del /f *.o doble
|
|
||||||
else
|
|
||||||
rm -f *.o doble
|
|
||||||
endif
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "numbers.h"
|
#include "numbers.h"
|
||||||
#include "bintree.h"
|
|
||||||
|
|
||||||
//TODO: getDuplicate und createNumbers implementieren
|
//TODO: getDuplicate und createNumbers implementieren
|
||||||
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
|
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
|
||||||
@@ -14,13 +13,100 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries.
|
||||||
|
// Returns NULL on errors.
|
||||||
unsigned int *createNumbers(unsigned int len)
|
unsigned int *createNumbers(unsigned int len)
|
||||||
{
|
{
|
||||||
|
if (len < 2) return NULL;
|
||||||
|
|
||||||
|
// Allocate memory for the array
|
||||||
|
unsigned int *numbers = malloc(len * sizeof(unsigned int));
|
||||||
|
if (!numbers) return NULL;
|
||||||
|
|
||||||
|
// Initialize random number generator
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
|
||||||
|
// We need to ensure len-1 unique numbers in range [1, 2*len]
|
||||||
|
unsigned int maxValue = 2 * len;
|
||||||
|
unsigned int uniqueCount = len - 1; // We'll generate len-1 unique values
|
||||||
|
|
||||||
|
// Generate unique numbers using a simple linear search approach
|
||||||
|
for (unsigned int i = 0; i < uniqueCount; i++) {
|
||||||
|
int isUnique;
|
||||||
|
unsigned int candidate;
|
||||||
|
|
||||||
|
// Keep generating until we find a unique number
|
||||||
|
do {
|
||||||
|
candidate = (rand() % maxValue) + 1; // Random number in [1, 2*len]
|
||||||
|
isUnique = 1;
|
||||||
|
|
||||||
|
// Check if candidate already exists in our array so far
|
||||||
|
for (unsigned int j = 0; j < i; j++) {
|
||||||
|
if (numbers[j] == candidate) {
|
||||||
|
isUnique = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!isUnique);
|
||||||
|
|
||||||
|
numbers[i] = candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we have len-1 unique numbers. Duplicate one of them.
|
||||||
|
// Choose a random index from the unique numbers
|
||||||
|
unsigned int duplicateIndex = rand() % uniqueCount;
|
||||||
|
unsigned int duplicateValue = numbers[duplicateIndex];
|
||||||
|
|
||||||
|
// Add the duplicate at the last position
|
||||||
|
numbers[len - 1] = duplicateValue;
|
||||||
|
|
||||||
|
// Shuffle the entire array to randomize the position of the duplicate
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
unsigned int swapIndex = rand() % len;
|
||||||
|
|
||||||
|
// Swap numbers[i] and numbers[swapIndex]
|
||||||
|
unsigned int temp = numbers[i];
|
||||||
|
numbers[i] = numbers[swapIndex];
|
||||||
|
numbers[swapIndex] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
||||||
{
|
{
|
||||||
|
if (!numbers || len < 2) return 0;
|
||||||
|
|
||||||
|
// Create a copy of the array since we need to sort it
|
||||||
|
unsigned int *copy = malloc(len * sizeof(unsigned int));
|
||||||
|
if (!copy) return 0;
|
||||||
|
|
||||||
|
memcpy(copy, numbers, len * sizeof(unsigned int));
|
||||||
|
|
||||||
|
// Simple bubble sort implementation (no external function dependencies)
|
||||||
|
for (unsigned int i = 0; i < len - 1; i++) {
|
||||||
|
for (unsigned int j = 0; j < len - i - 1; j++) {
|
||||||
|
if (copy[j] > copy[j + 1]) {
|
||||||
|
// Swap if out of order
|
||||||
|
unsigned int temp = copy[j];
|
||||||
|
copy[j] = copy[j + 1];
|
||||||
|
copy[j + 1] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find the duplicate by checking adjacent elements
|
||||||
|
unsigned int duplicate = 0;
|
||||||
|
for (unsigned int i = 0; i < len - 1; i++) {
|
||||||
|
if (copy[i] == copy[i + 1]) {
|
||||||
|
duplicate = copy[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(copy);
|
||||||
|
return duplicate;
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
// 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);
|
||||||
|
|
||||||
// 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.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ This means that with each new element all other elements are pushed deeper into
|
|||||||
The latest element is taken from the stack. */
|
The latest element is taken from the stack. */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
typedef struct Stack_node StackNode;
|
||||||
//TODO: passenden Datentyp als struct anlegen
|
//TODO: passenden Datentyp als struct anlegen
|
||||||
|
|
||||||
// Pushes data as pointer onto the stack.
|
// Pushes data as pointer onto the stack.
|
||||||
|
|||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
// Helper: create int on heap
|
||||||
|
static int *make_int(int value) {
|
||||||
|
int *p = malloc(sizeof(int));
|
||||||
|
if (!p) {
|
||||||
|
fprintf(stderr, "Memory allocation failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
*p = value;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
printf("Running stack unit tests...\n");
|
||||||
|
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
|
||||||
|
// --- Test 1: push() on empty stack ---
|
||||||
|
int *a = make_int(10);
|
||||||
|
stack = push(stack, a);
|
||||||
|
assert(stack != NULL);
|
||||||
|
assert(top(stack) == a);
|
||||||
|
assert(*(int*)top(stack) == 10);
|
||||||
|
|
||||||
|
// --- Test 2: push() on non-empty stack ---
|
||||||
|
int *b = make_int(20);
|
||||||
|
stack = push(stack, b);
|
||||||
|
assert(top(stack) == b);
|
||||||
|
assert(*(int*)top(stack) == 20);
|
||||||
|
|
||||||
|
// --- Test 3: pop() returns previous element ---
|
||||||
|
stack = pop(stack); // removes 20
|
||||||
|
assert(top(stack) == a);
|
||||||
|
assert(*(int*)top(stack) == 10);
|
||||||
|
|
||||||
|
// --- Test 4: pop() on single element returns NULL ---
|
||||||
|
stack = pop(stack); // removes 10
|
||||||
|
assert(stack == NULL);
|
||||||
|
|
||||||
|
// --- Test 5: pop() on empty stack returns NULL ---
|
||||||
|
stack = pop(stack);
|
||||||
|
assert(stack == NULL);
|
||||||
|
|
||||||
|
// --- Test 6: clearStack() empties a multi-element stack ---
|
||||||
|
int *c = make_int(1);
|
||||||
|
int *d = make_int(2);
|
||||||
|
int *e = make_int(3);
|
||||||
|
stack = push(stack, c);
|
||||||
|
stack = push(stack, d);
|
||||||
|
stack = push(stack, e);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
stack = NULL;
|
||||||
|
|
||||||
|
// free allocated ints
|
||||||
|
free(a);
|
||||||
|
free(b);
|
||||||
|
free(c);
|
||||||
|
free(d);
|
||||||
|
free(e);
|
||||||
|
|
||||||
|
printf("All tests passed successfully.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
// Helper: create int on heap
|
||||||
|
static int *make_int(int value) {
|
||||||
|
int *p = malloc(sizeof(int));
|
||||||
|
if (!p) {
|
||||||
|
fprintf(stderr, "Memory allocation failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
*p = value;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
printf("Running stack unit tests...\n");
|
||||||
|
|
||||||
|
StackNode *stack = NULL;
|
||||||
|
|
||||||
|
// --- Test 1: push() on empty stack ---
|
||||||
|
int *a = make_int(10);
|
||||||
|
stack = push(stack, a);
|
||||||
|
assert(stack != NULL);
|
||||||
|
assert(top(stack) == a);
|
||||||
|
assert(*(int*)top(stack) == 10);
|
||||||
|
|
||||||
|
// --- Test 2: push() on non-empty stack ---
|
||||||
|
int *b = make_int(20);
|
||||||
|
stack = push(stack, b);
|
||||||
|
assert(top(stack) == b);
|
||||||
|
assert(*(int*)top(stack) == 20);
|
||||||
|
|
||||||
|
// --- Test 3: pop() returns previous element ---
|
||||||
|
stack = pop(stack); // removes 20
|
||||||
|
assert(top(stack) == a);
|
||||||
|
assert(*(int*)top(stack) == 10);
|
||||||
|
|
||||||
|
// --- Test 4: pop() on single element returns NULL ---
|
||||||
|
stack = pop(stack); // removes 10
|
||||||
|
assert(stack == NULL);
|
||||||
|
|
||||||
|
// --- Test 5: pop() on empty stack returns NULL ---
|
||||||
|
stack = pop(stack);
|
||||||
|
assert(stack == NULL);
|
||||||
|
|
||||||
|
// --- Test 6: clearStack() empties a multi-element stack ---
|
||||||
|
int *c = make_int(1);
|
||||||
|
int *d = make_int(2);
|
||||||
|
int *e = make_int(3);
|
||||||
|
stack = push(stack, c);
|
||||||
|
stack = push(stack, d);
|
||||||
|
stack = push(stack, e);
|
||||||
|
|
||||||
|
clearStack(stack);
|
||||||
|
// stack pointer still points to old top; we must reset manually
|
||||||
|
stack = NULL;
|
||||||
|
|
||||||
|
// no crash = success
|
||||||
|
|
||||||
|
// free remaining data
|
||||||
|
free(a);
|
||||||
|
free(b);
|
||||||
|
free(c);
|
||||||
|
free(d);
|
||||||
|
free(e);
|
||||||
|
|
||||||
|
printf("All tests passed successfully.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user