Compare commits
6
Commits
a3d0585ac1
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7a872252a | ||
|
|
de9e0a3357 | ||
|
|
746b9b7219 | ||
|
|
1f3fba80ec | ||
|
|
1d363980f6 | ||
|
|
4ce3a6aac0
|
+60
-1
@@ -1,3 +1,62 @@
|
|||||||
doble_initial.exe
|
# ---> C
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
*.o
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
*.exe
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
Startcode/doble_initial
|
||||||
|
Startcode/doble
|
||||||
|
Startcode/unitTests
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
# IDE folders
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,36 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "stack.h"
|
||||||
|
#include "bintree.h"
|
||||||
|
|
||||||
|
//TODO: binären Suchbaum implementieren
|
||||||
|
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
|
||||||
|
* `clearTree`: gibt den gesamten Baum frei (rekursiv),
|
||||||
|
* `treeSize`: zählt die Knoten im Baum (rekursiv),
|
||||||
|
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Releases all memory resources (including data copies).
|
||||||
|
void clearTree(TreeNode *root)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of entries in the tree given by root.
|
||||||
|
unsigned int treeSize(const TreeNode *root)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef BINTREE_H
|
||||||
|
#define BINTREE_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef int (*CompareFctType)(const void *arg1, const void *arg2);
|
||||||
|
|
||||||
|
typedef struct node
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
struct node *left;
|
||||||
|
struct node *right;
|
||||||
|
} TreeNode;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// 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);
|
||||||
|
// Releases all memory resources (including data copies).
|
||||||
|
void clearTree(TreeNode *root);
|
||||||
|
// Returns the number of entries in the tree given by root.
|
||||||
|
unsigned int treeSize(const TreeNode *root);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
player1;3999
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
CC = gcc
|
||||||
|
FLAGS = -g -Wall -lm
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
include makefile_windows.variables
|
||||||
|
else
|
||||||
|
UNAME = $(shell uname)
|
||||||
|
ifeq ($(UNAME),Linux)
|
||||||
|
include makefile_linux.variables
|
||||||
|
else
|
||||||
|
include makefile_mac.variables
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
raylibfolder = ./raylib
|
||||||
|
unityfolder = ./unity
|
||||||
|
|
||||||
|
# --------------------------
|
||||||
|
# Initiales Programm bauen (zum ausprobieren)
|
||||||
|
# --------------------------
|
||||||
|
doble_initial:
|
||||||
|
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
||||||
|
|
||||||
|
# --------------------------
|
||||||
|
# Selbst implementiertes Programm bauen
|
||||||
|
# --------------------------
|
||||||
|
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
|
||||||
|
|
||||||
|
doble : main.o $(program_obj_files)
|
||||||
|
$(CC) $(FLAGS) $^ -o doble
|
||||||
|
|
||||||
|
$(program_obj_files): %.o: %.c
|
||||||
|
$(CC) -c $(FLAGS) $^ -o $@
|
||||||
|
|
||||||
|
# --------------------------
|
||||||
|
# Unit Tests
|
||||||
|
# --------------------------
|
||||||
|
unitTests:
|
||||||
|
echo "needs to be implemented"
|
||||||
|
|
||||||
|
# --------------------------
|
||||||
|
# Clean
|
||||||
|
# --------------------------
|
||||||
|
clean:
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
del /f *.o doble
|
||||||
|
else
|
||||||
|
rm -f *.o doble
|
||||||
|
endif
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#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.
|
||||||
|
* 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. */
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#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. */
|
||||||
|
|
||||||
|
// Pushes data as pointer onto the stack.
|
||||||
|
StackNode *push(StackNode *stack, void *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the data of the top element.
|
||||||
|
void *top(StackNode *stack)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears stack and releases all memory.
|
||||||
|
void clearStack(StackNode *stack)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef STACK_H
|
||||||
|
#define STACK_H
|
||||||
|
|
||||||
|
/* A stack is a special type of queue which uses the LIFO (last in, first out) principle.
|
||||||
|
This means that with each new element all other elements are pushed deeper into the stack.
|
||||||
|
The latest element is taken from the stack. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
//TODO: passenden Datentyp als struct anlegen
|
||||||
|
|
||||||
|
// Pushes data as pointer onto the stack.
|
||||||
|
StackNode *push(StackNode *stack, void *data);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Returns the data of the top element.
|
||||||
|
void *top(StackNode *stack);
|
||||||
|
|
||||||
|
// Clears stack and releases all memory.
|
||||||
|
void clearStack(StackNode *stack);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
#include "bintree.h"
|
|
||||||
#include "stack.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// TODO: binären Suchbaum implementieren
|
|
||||||
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
|
|
||||||
* `clearTree`: gibt den gesamten Baum frei (rekursiv),
|
|
||||||
* `treeSize`: zählt die Knoten im Baum (rekursiv),
|
|
||||||
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
|
|
||||||
|
|
||||||
// typedef int (*CompareFctType)(const void *arg1, const void *arg2);
|
|
||||||
// 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).
|
|
||||||
|
|
||||||
void copyData(void *dest, const void *src, size_t size) {
|
|
||||||
unsigned char *d = dest;
|
|
||||||
const unsigned char *s = src;
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
d[i] = s[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
|
|
||||||
CompareFctType compareFct, int *isDuplicate) {
|
|
||||||
|
|
||||||
// isDuplicate initialisieren (auf 0 setzen)
|
|
||||||
if (isDuplicate) {
|
|
||||||
*isDuplicate = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// leerer Baum
|
|
||||||
if (root == NULL) {
|
|
||||||
TreeNode *node = malloc(sizeof(TreeNode));
|
|
||||||
node->data = malloc(dataSize);
|
|
||||||
copyData(node->data, data, dataSize);
|
|
||||||
node->left = NULL;
|
|
||||||
node->right = NULL;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mit compareFct <0 links >0 rechts =0 Duplikat
|
|
||||||
int cmp = compareFct(data, root->data);
|
|
||||||
|
|
||||||
if (cmp < 0) {
|
|
||||||
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
|
|
||||||
} else if (cmp > 0) {
|
|
||||||
root->right =
|
|
||||||
addToTree(root->right, data, dataSize, compareFct, isDuplicate);
|
|
||||||
} else {
|
|
||||||
// isDuplicate auf 1 setzen
|
|
||||||
if (isDuplicate) {
|
|
||||||
*isDuplicate = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
// Neue Iteration starten
|
|
||||||
if (root != NULL) {
|
|
||||||
clearStack(&stack);
|
|
||||||
|
|
||||||
TreeNode *curr = root;
|
|
||||||
while (curr != NULL) {
|
|
||||||
stack = push(stack, curr);
|
|
||||||
curr = curr->left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack == NULL)
|
|
||||||
return NULL; // alles durchlaufen
|
|
||||||
|
|
||||||
// Oberstes Element abrufen
|
|
||||||
TreeNode *node = (TreeNode *)top(stack);
|
|
||||||
stack = pop(stack);
|
|
||||||
|
|
||||||
// Rechten Teilbaum pushen
|
|
||||||
TreeNode *curr = node->right;
|
|
||||||
while (curr != NULL) {
|
|
||||||
stack = push(stack, curr);
|
|
||||||
curr = curr->left;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Releases all memory resources (including data copies).
|
|
||||||
void clearTree(TreeNode *root) {
|
|
||||||
if (root == NULL)
|
|
||||||
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 == NULL)
|
|
||||||
return 0;
|
|
||||||
return 1 + treeSize(root->left) + treeSize(root->right);
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef BINTREE_H
|
|
||||||
#define BINTREE_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
typedef int (*CompareFctType)(const void *arg1, const void *arg2);
|
|
||||||
|
|
||||||
typedef struct node {
|
|
||||||
void *data;
|
|
||||||
struct node *left;
|
|
||||||
struct node *right;
|
|
||||||
} TreeNode;
|
|
||||||
|
|
||||||
void copyData(void *dest, const void *src, size_t size);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
// 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);
|
|
||||||
// Releases all memory resources (including data copies).
|
|
||||||
void clearTree(TreeNode *root);
|
|
||||||
// Returns the number of entries in the tree given by root.
|
|
||||||
unsigned int treeSize(const TreeNode *root);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
Kristin;6962
|
|
||||||
Kristin;5975
|
|
||||||
krisp;4986
|
|
||||||
krisp;4985
|
|
||||||
Kristin;4972
|
|
||||||
player1;3999
|
|
||||||
krisp;3991
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
CC = gcc
|
|
||||||
FLAGS = -g -Wall -lm
|
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
|
||||||
include makefile_windows.variables
|
|
||||||
else
|
|
||||||
UNAME = $(shell uname)
|
|
||||||
ifeq ($(UNAME),Linux)
|
|
||||||
include makefile_linux.variables
|
|
||||||
else
|
|
||||||
include makefile_mac.variables
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
raylibfolder = ./raylib
|
|
||||||
unityfolder = ./unity
|
|
||||||
|
|
||||||
# --------------------------
|
|
||||||
# Initiales Programm bauen (zum ausprobieren)
|
|
||||||
# --------------------------
|
|
||||||
doble_initial:
|
|
||||||
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
|
|
||||||
|
|
||||||
# --------------------------
|
|
||||||
# Selbst implementiertes Programm bauen
|
|
||||||
# --------------------------
|
|
||||||
# alle Objektdateien
|
|
||||||
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
|
|
||||||
# alle ausführbaren Dateien zu ausführbarem Programm linken
|
|
||||||
doble : main.o $(program_obj_files)
|
|
||||||
$(CC) $(FLAGS) $^ -o doble
|
|
||||||
# Regel Kompilieren allgemein
|
|
||||||
$(program_obj_files): %.o: %.c
|
|
||||||
$(CC) -c $(FLAGS) $^ -o $@
|
|
||||||
|
|
||||||
# --------------------------
|
|
||||||
# Unit Tests
|
|
||||||
# --------------------------
|
|
||||||
|
|
||||||
STACK_TEST_BIN = runStackTests
|
|
||||||
NUMBERS_TEST_BIN = runNumbersTests
|
|
||||||
BINARY_TEST_BIN = runBinaryTests
|
|
||||||
|
|
||||||
# --- Stack Tests ---
|
|
||||||
stackTests: stack.o test_stack.o
|
|
||||||
$(CC) $(FLAGS) -I$(unityfolder) -o $(STACK_TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c
|
|
||||||
|
|
||||||
test_stack.o: test_stack.c
|
|
||||||
$(CC) $(FLAGS) -I$(unityfolder) -c test_stack.c -o test_stack.o
|
|
||||||
|
|
||||||
|
|
||||||
# --- Numbers Tests ---
|
|
||||||
numbersTests: numbers.o bintree.o stack.o test_numbers.o
|
|
||||||
$(CC) $(FLAGS) -I$(unityfolder) -o $(NUMBERS_TEST_BIN) numbers.o bintree.o stack.o test_numbers.o $(unityfolder)/unity.c
|
|
||||||
|
|
||||||
test_numbers.o: test_numbers.c
|
|
||||||
$(CC) $(FLAGS) -I$(unityfolder) -c test_numbers.c -o test_numbers.o
|
|
||||||
|
|
||||||
|
|
||||||
# --- Binary Tree Tests ---
|
|
||||||
binaryTests: bintree.o stack.o test_binary.o
|
|
||||||
$(CC) $(FLAGS) -I$(unityfolder) -o $(BINARY_TEST_BIN) bintree.o stack.o test_binary.o $(unityfolder)/unity.c
|
|
||||||
|
|
||||||
test_binary.o: test_binary.c
|
|
||||||
$(CC) $(FLAGS) -I$(unityfolder) -c test_binary.c -o test_binary.o
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------
|
|
||||||
# Clean
|
|
||||||
# --------------------------
|
|
||||||
clean:
|
|
||||||
rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN)
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
#include "numbers.h"
|
|
||||||
#include "bintree.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
int compareUnsignedInt(const void *a, const void *b) {
|
|
||||||
unsigned int x = *(unsigned int *)a;
|
|
||||||
unsigned int y = *(unsigned int *)b;
|
|
||||||
|
|
||||||
if (x < y)
|
|
||||||
return -1;
|
|
||||||
if (x > y)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: getDuplicate und createNumbers implementieren
|
|
||||||
/**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an
|
|
||||||
* Zufallszahlen. 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. */
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
if (len < 2)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
unsigned int *arr = malloc(sizeof(unsigned int) * len);
|
|
||||||
if (!arr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
TreeNode *root = NULL;
|
|
||||||
srand((unsigned int)time(NULL));
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < len - 1; i++) {
|
|
||||||
unsigned int num;
|
|
||||||
int isDuplicate;
|
|
||||||
|
|
||||||
do {
|
|
||||||
num = (rand() % (2 * len)) + 1;
|
|
||||||
isDuplicate = 0;
|
|
||||||
|
|
||||||
root = addToTree(root, &num, sizeof(unsigned int), compareUnsignedInt,
|
|
||||||
&isDuplicate);
|
|
||||||
|
|
||||||
} while (isDuplicate); // nur akzeptieren, wenn eindeutig
|
|
||||||
|
|
||||||
arr[i] = num;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jetzt gezielt EIN Duplikat erzeugen
|
|
||||||
unsigned int duplicateIndex = rand() % (len - 1);
|
|
||||||
arr[len - 1] = arr[duplicateIndex];
|
|
||||||
|
|
||||||
clearTree(root);
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
unsigned int *copy = malloc(sizeof(unsigned int) * len);
|
|
||||||
if (!copy)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy(copy, numbers, sizeof(unsigned int) * len);
|
|
||||||
|
|
||||||
// Sortierung
|
|
||||||
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
|
|
||||||
|
|
||||||
// Duplikat finden: zwei gleiche nebeneinander
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
#include "stack.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/*typedef struct {
|
|
||||||
|
|
||||||
void *data;
|
|
||||||
struct StackNode *next;
|
|
||||||
|
|
||||||
} StackNode;*/
|
|
||||||
|
|
||||||
// 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. */
|
|
||||||
|
|
||||||
// [A] -> [B] -> [C] -> NULL
|
|
||||||
// head -> stack.next
|
|
||||||
|
|
||||||
StackNode *createNode(void *data) {
|
|
||||||
|
|
||||||
StackNode *node = malloc(sizeof(StackNode));
|
|
||||||
|
|
||||||
if (node == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
node->data = data;
|
|
||||||
node->next = NULL;
|
|
||||||
node->prev = NULL;
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pushes data as pointer onto the stack.
|
|
||||||
StackNode *push(StackNode *stack, void *data) {
|
|
||||||
|
|
||||||
StackNode *newNode = createNode(data);
|
|
||||||
|
|
||||||
if (newNode == NULL) {
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
newNode->next = stack;
|
|
||||||
if (stack != NULL) {
|
|
||||||
stack->prev = newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
if (stack == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
StackNode *nextNode = stack->next;
|
|
||||||
if (nextNode != NULL) {
|
|
||||||
nextNode->prev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(stack);
|
|
||||||
|
|
||||||
stack = NULL;
|
|
||||||
|
|
||||||
return nextNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the data of the top element.
|
|
||||||
void *top(StackNode *stack) { return stack ? stack->data : NULL; }
|
|
||||||
|
|
||||||
// Clears stack and releases all memory.
|
|
||||||
void clearStack(StackNode **stack) {
|
|
||||||
|
|
||||||
while (*stack != NULL) {
|
|
||||||
StackNode *next = (*stack)->next;
|
|
||||||
free(*stack);
|
|
||||||
*stack = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#ifndef STACK_H
|
|
||||||
#define STACK_H
|
|
||||||
|
|
||||||
/* A stack is a special type of queue which uses the LIFO (last in, first out)
|
|
||||||
principle. This means that with each new element all other elements are pushed
|
|
||||||
deeper into the stack. The latest element is taken from the stack. */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
// TODO: passenden Datentyp als struct anlegen
|
|
||||||
|
|
||||||
typedef struct StackNode {
|
|
||||||
|
|
||||||
void *data;
|
|
||||||
struct StackNode *next;
|
|
||||||
struct StackNode *prev;
|
|
||||||
|
|
||||||
} StackNode;
|
|
||||||
|
|
||||||
StackNode *createNode(void *data);
|
|
||||||
|
|
||||||
// Pushes data as pointer onto the stack.
|
|
||||||
StackNode *push(StackNode *stack, void *data);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Returns the data of the top element.
|
|
||||||
void *top(StackNode *stack);
|
|
||||||
|
|
||||||
// Clears stack and releases all memory.
|
|
||||||
void clearStack(StackNode **stack);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
-105
@@ -1,105 +0,0 @@
|
|||||||
#include "unity.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "bintree.h"
|
|
||||||
int compareUnsignedInt(const void *a, const void *b) {
|
|
||||||
unsigned int x = *(unsigned int *)a;
|
|
||||||
unsigned int y = *(unsigned int *)b;
|
|
||||||
|
|
||||||
if (x < y)
|
|
||||||
return -1;
|
|
||||||
if (x > y)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeNode *root = NULL;
|
|
||||||
|
|
||||||
void setUp(void) {
|
|
||||||
root = NULL; // vor jedem Test leeren
|
|
||||||
}
|
|
||||||
|
|
||||||
void tearDown(void) { clearTree(root); }
|
|
||||||
|
|
||||||
// Test, ob addToTree Knoten korrekt hinzufügt
|
|
||||||
void test_addToTree_basic(void) {
|
|
||||||
int isDup;
|
|
||||||
unsigned int val = 10;
|
|
||||||
root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup);
|
|
||||||
TEST_ASSERT_NOT_NULL(root);
|
|
||||||
TEST_ASSERT_EQUAL_UINT(10, *(unsigned int *)root->data);
|
|
||||||
TEST_ASSERT_EQUAL_INT(0, isDup);
|
|
||||||
TEST_ASSERT_EQUAL_UINT(1, treeSize(root));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test, dass Duplikate erkannt werden
|
|
||||||
void test_addToTree_duplicate(void) {
|
|
||||||
int isDup;
|
|
||||||
unsigned int val1 = 10, val2 = 10;
|
|
||||||
root = addToTree(root, &val1, sizeof(val1), compareUnsignedInt, &isDup);
|
|
||||||
TEST_ASSERT_EQUAL_INT(0, isDup);
|
|
||||||
root = addToTree(root, &val2, sizeof(val2), compareUnsignedInt, &isDup);
|
|
||||||
TEST_ASSERT_EQUAL_INT(1, isDup);
|
|
||||||
TEST_ASSERT_EQUAL_UINT(1, treeSize(root)); // Duplikate nicht hinzufügen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test nextTreeData Traversierung
|
|
||||||
void test_nextTreeData_in_order(void) {
|
|
||||||
unsigned int values[] = {20, 10, 30};
|
|
||||||
int isDup;
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
root = addToTree(root, &values[i], sizeof(values[i]), compareUnsignedInt,
|
|
||||||
&isDup);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int expected[] = {10, 20, 30};
|
|
||||||
int idx = 0;
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
// **Neue Iteration starten**
|
|
||||||
data = nextTreeData(root);
|
|
||||||
while (data != NULL) {
|
|
||||||
TEST_ASSERT_EQUAL_UINT(expected[idx], *(unsigned int *)data);
|
|
||||||
idx++;
|
|
||||||
data = nextTreeData(NULL); // weitere Elemente abrufen
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL_INT(3, idx); // alle 3 Knoten besucht
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test clearTree gibt Speicher frei
|
|
||||||
void test_clearTree(void) {
|
|
||||||
unsigned int val = 42;
|
|
||||||
int isDup;
|
|
||||||
root = addToTree(root, &val, sizeof(val), compareUnsignedInt, &isDup);
|
|
||||||
clearTree(root);
|
|
||||||
root = NULL; // clearTree löscht nicht die root-Variable selbst
|
|
||||||
TEST_ASSERT_NULL(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test treeSize zählt korrekt
|
|
||||||
void test_treeSize(void) {
|
|
||||||
unsigned int vals[] = {10, 20, 5};
|
|
||||||
int isDup;
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
root =
|
|
||||||
addToTree(root, &vals[i], sizeof(vals[i]), compareUnsignedInt, &isDup);
|
|
||||||
}
|
|
||||||
TEST_ASSERT_EQUAL_UINT(3, treeSize(root));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
UNITY_BEGIN();
|
|
||||||
|
|
||||||
printf(
|
|
||||||
"\n------------------------binarytree test------------------------\n\n");
|
|
||||||
|
|
||||||
RUN_TEST(test_addToTree_basic);
|
|
||||||
RUN_TEST(test_addToTree_duplicate);
|
|
||||||
RUN_TEST(test_nextTreeData_in_order);
|
|
||||||
RUN_TEST(test_clearTree);
|
|
||||||
RUN_TEST(test_treeSize);
|
|
||||||
return UNITY_END();
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#include "unity.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "numbers.h"
|
|
||||||
|
|
||||||
#define TEST_ARRAY_LEN 100
|
|
||||||
|
|
||||||
void test_createNumbers_length(void) {
|
|
||||||
unsigned int *arr = createNumbers(TEST_ARRAY_LEN);
|
|
||||||
TEST_ASSERT_NOT_NULL(arr);
|
|
||||||
free(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_createNumbers_single_duplicate(void) {
|
|
||||||
unsigned int *arr = createNumbers(TEST_ARRAY_LEN);
|
|
||||||
TEST_ASSERT_NOT_NULL(arr);
|
|
||||||
|
|
||||||
unsigned int duplicate = getDuplicate(arr, TEST_ARRAY_LEN);
|
|
||||||
TEST_ASSERT_TRUE(duplicate > 0);
|
|
||||||
|
|
||||||
unsigned int count = 0;
|
|
||||||
for (unsigned int i = 0; i < TEST_ARRAY_LEN; i++) {
|
|
||||||
if (arr[i] == duplicate) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TEST_ASSERT_EQUAL_UINT(2, count);
|
|
||||||
|
|
||||||
free(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_getDuplicate_manual_array(void) {
|
|
||||||
unsigned int numbers[5] = {10, 20, 30, 40, 20};
|
|
||||||
unsigned int dup = getDuplicate(numbers, 5);
|
|
||||||
TEST_ASSERT_EQUAL_UINT(20, dup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_getDuplicate_invalid_input(void) {
|
|
||||||
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(NULL, 5));
|
|
||||||
unsigned int arr[1] = {42};
|
|
||||||
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(arr, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUp(void) {}
|
|
||||||
void tearDown(void) {}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
|
|
||||||
UNITY_BEGIN();
|
|
||||||
|
|
||||||
printf("\n------------------------numbers test------------------------\n\n");
|
|
||||||
|
|
||||||
RUN_TEST(test_createNumbers_length);
|
|
||||||
RUN_TEST(test_createNumbers_single_duplicate);
|
|
||||||
RUN_TEST(test_getDuplicate_manual_array);
|
|
||||||
RUN_TEST(test_getDuplicate_invalid_input);
|
|
||||||
|
|
||||||
return UNITY_END();
|
|
||||||
}
|
|
||||||
-110
@@ -1,110 +0,0 @@
|
|||||||
#include "unity.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "stack.h"
|
|
||||||
|
|
||||||
void test_createNode(void) {
|
|
||||||
|
|
||||||
int testInt = 26;
|
|
||||||
StackNode *testNode = createNode(&testInt);
|
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(testNode);
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data);
|
|
||||||
TEST_ASSERT_NULL(testNode->next);
|
|
||||||
TEST_ASSERT_NULL(testNode->prev);
|
|
||||||
|
|
||||||
free(testNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_pushDataToStack(void) {
|
|
||||||
|
|
||||||
int testInt = 27;
|
|
||||||
|
|
||||||
StackNode *testNode = push(NULL, &testInt);
|
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(testNode);
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInt, testNode->data);
|
|
||||||
TEST_ASSERT_NULL(testNode->next);
|
|
||||||
TEST_ASSERT_NULL(testNode->prev);
|
|
||||||
|
|
||||||
free(testNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_deleteTopElement(void) {
|
|
||||||
|
|
||||||
int testInts[] = {10, 20, 30};
|
|
||||||
StackNode *stack = NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
stack = push(stack, &testInts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data);
|
|
||||||
|
|
||||||
stack = pop(stack);
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data);
|
|
||||||
|
|
||||||
stack = pop(stack);
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data);
|
|
||||||
|
|
||||||
stack = pop(stack);
|
|
||||||
TEST_ASSERT_NULL(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_returnData(void) {
|
|
||||||
|
|
||||||
int testInts[] = {10, 20, 30};
|
|
||||||
StackNode *stack = NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
stack = push(stack, &testInts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack));
|
|
||||||
|
|
||||||
if (stack->next != NULL) {
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->next->data);
|
|
||||||
if (stack->next->next != NULL) {
|
|
||||||
TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->next->next->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StackNode *last = stack;
|
|
||||||
while (last->next != NULL) {
|
|
||||||
last = last->next;
|
|
||||||
}
|
|
||||||
TEST_ASSERT_NULL(last->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_clearStack(void) {
|
|
||||||
int testInts[] = {1, 2, 3, 4, 5};
|
|
||||||
StackNode *stack = NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
stack = push(stack, &testInts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearStack(&stack);
|
|
||||||
|
|
||||||
TEST_ASSERT_NULL(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUp(void) {}
|
|
||||||
void tearDown(void) {}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
|
|
||||||
UNITY_BEGIN();
|
|
||||||
|
|
||||||
printf("\n------------------------stack test------------------------\n\n");
|
|
||||||
|
|
||||||
RUN_TEST(test_createNode);
|
|
||||||
RUN_TEST(test_pushDataToStack);
|
|
||||||
RUN_TEST(test_deleteTopElement);
|
|
||||||
RUN_TEST(test_returnData);
|
|
||||||
RUN_TEST(test_clearStack);
|
|
||||||
|
|
||||||
return UNITY_END();
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user