Compare commits
8
Commits
63f92a83fd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
526f1c3884 | ||
|
|
941374cbc2 | ||
|
|
9f0191845d | ||
|
|
d264a7513e | ||
|
|
2801e4b709 | ||
|
|
43a953eaa6 | ||
|
|
c2955be947 | ||
|
|
2c8974b6c6 |
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
|
||||
// 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.
|
||||
// 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.
|
||||
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).
|
||||
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.
|
||||
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
|
||||
FLAGS = -g -Wall -lm
|
||||
FLAGS = -g -Wall
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
include makefile_windows.variables
|
||||
RM = del /f
|
||||
else
|
||||
UNAME = $(shell uname)
|
||||
ifeq ($(UNAME),Linux)
|
||||
@@ -10,40 +14,49 @@ else
|
||||
else
|
||||
include makefile_mac.variables
|
||||
endif
|
||||
RM = rm -f
|
||||
endif
|
||||
|
||||
raylibfolder = ./raylib
|
||||
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:
|
||||
$(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)
|
||||
$(CC) $(FLAGS) $^ -o doble
|
||||
# Compile testStack.c en un exécutable testStack
|
||||
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
|
||||
$(CC) -c $(FLAGS) $^ -o $@
|
||||
|
||||
# --------------------------
|
||||
# Unit Tests
|
||||
# --------------------------
|
||||
unitTests:
|
||||
echo "needs to be implemented"
|
||||
testStack.o: testStack.c
|
||||
$(CC) $(FLAGS) -c testStack.c -o testStack.o
|
||||
|
||||
# --------------------------
|
||||
# Clean
|
||||
# --------------------------
|
||||
clean:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
del /f *.o doble
|
||||
else
|
||||
rm -f *.o doble
|
||||
endif
|
||||
$(RM) *.o doble testStack doble_initial
|
||||
@@ -1,9 +1,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "numbers.h"
|
||||
#include "bintree.h"
|
||||
|
||||
|
||||
//TODO: getDuplicate und createNumbers implementieren
|
||||
/* * * 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 NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while
|
||||
// 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)
|
||||
{
|
||||
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.
|
||||
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 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);
|
||||
|
||||
// Returns only the only number in numbers which is present twice. Returns zero on errors.
|
||||
|
||||
@@ -1,33 +1,43 @@
|
||||
#include <stdlib.h>
|
||||
#include "stack.h"
|
||||
|
||||
//TODO: grundlegende Stackfunktionen implementieren:
|
||||
/* * `push`: legt ein Element oben auf den Stack,
|
||||
* `pop`: entfernt das oberste Element,
|
||||
* `top`: liefert das oberste Element zurück,
|
||||
* `clearStack`: gibt den gesamten Speicher frei. */
|
||||
typedef struct Stack_node {
|
||||
void *data;
|
||||
struct Stack_node *next;
|
||||
} StackNode;
|
||||
|
||||
// Pushes data as pointer onto the stack.
|
||||
StackNode *push(StackNode *stack, void *data)
|
||||
{
|
||||
// Pushes data onto the stack.
|
||||
// Returns the new top of the stack.
|
||||
StackNode *push(StackNode *stack, void *data) {
|
||||
StackNode *node = malloc(sizeof(StackNode));
|
||||
if (!node) return stack; // allocation failed → leave unchanged
|
||||
|
||||
node->data = data;
|
||||
node->next = stack;
|
||||
return node; // new top element
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Deletes the top element and returns the new stack top.
|
||||
// Caller must free the *data* itself.
|
||||
StackNode *pop(StackNode *stack) {
|
||||
if (!stack) return NULL;
|
||||
|
||||
StackNode *next = stack->next;
|
||||
free(stack); // free only the node, NOT the data
|
||||
return next;
|
||||
}
|
||||
|
||||
// Returns the data of the top element.
|
||||
void *top(StackNode *stack)
|
||||
{
|
||||
|
||||
// Returns the data at the top of the stack.
|
||||
void *top(StackNode *stack) {
|
||||
if (!stack) return NULL;
|
||||
return stack->data;
|
||||
}
|
||||
|
||||
// Clears stack and releases all memory.
|
||||
void clearStack(StackNode *stack)
|
||||
{
|
||||
|
||||
}
|
||||
// Clears entire stack (but does NOT free the data).
|
||||
void clearStack(StackNode *stack) {
|
||||
while (stack) {
|
||||
StackNode *next = stack->next;
|
||||
free(stack);
|
||||
stack = next;
|
||||
}
|
||||
}
|
||||
@@ -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. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct Stack_node StackNode;
|
||||
//TODO: passenden Datentyp als struct anlegen
|
||||
|
||||
// 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