erste version
This commit is contained in:
parent
55532cbb42
commit
68563ec297
108
bintree.c
108
bintree.c
@ -1,36 +1,106 @@
|
||||
#include <string.h>
|
||||
#include "stack.h"
|
||||
#include "bintree.h"
|
||||
#include "stack.h"
|
||||
#include <string.h>
|
||||
|
||||
//TODO: binären Suchbaum implementieren
|
||||
// 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. */
|
||||
* `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)
|
||||
{
|
||||
// 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).
|
||||
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
|
||||
CompareFctType compareFct, int *isDuplicate) {
|
||||
|
||||
if (isDuplicate) {
|
||||
*isDuplicate = 0;
|
||||
}
|
||||
|
||||
if (root == NULL) {
|
||||
TreeNode *node = malloc(sizeof(TreeNode));
|
||||
node->data = malloc(dataSize);
|
||||
memcpy(node->data, data, dataSize);
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
return node;
|
||||
}
|
||||
|
||||
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 {
|
||||
// Duplikat
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Alle linken Kinder pushen
|
||||
while (curr != NULL) {
|
||||
stack = push(stack, curr);
|
||||
curr = curr->left;
|
||||
}
|
||||
}
|
||||
|
||||
// Wenn leer → fertig
|
||||
if (stack == NULL)
|
||||
return NULL;
|
||||
|
||||
// Oberstes Element lesen
|
||||
TreeNode *node = (TreeNode *)stack->data;
|
||||
stack = pop(stack);
|
||||
|
||||
// Jetzt den rechten Teilbaum verarbeiten
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
unsigned int treeSize(const TreeNode *root) {
|
||||
|
||||
if (root == NULL)
|
||||
return 0;
|
||||
return 1 + treeSize(root->left) + treeSize(root->right);
|
||||
}
|
||||
@ -1,2 +1,5 @@
|
||||
krisp;4986
|
||||
krisp;4985
|
||||
Kristin;4972
|
||||
player1;3999
|
||||
krisp;3991
|
||||
|
||||
31
makefile
31
makefile
@ -36,16 +36,39 @@ $(program_obj_files): %.o: %.c
|
||||
# Unit Tests
|
||||
# --------------------------
|
||||
|
||||
TEST_BIN = runTests
|
||||
STACK_TEST_BIN = runStackTests
|
||||
NUMBERS_TEST_BIN = runNumbersTests
|
||||
BINARY_TEST_BIN = runBinaryTests
|
||||
|
||||
unitTests: stack.o test_stack.o
|
||||
$(CC) $(FLAGS) -I$(unityfolder) -o $(TEST_BIN) stack.o test_stack.o $(unityfolder)/unity.c
|
||||
# --- 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
|
||||
rm -f *.o doble $(STACK_TEST_BIN) $(NUMBERS_TEST_BIN) $(BINARY_TEST_BIN)
|
||||
101
numbers.c
101
numbers.c
@ -1,26 +1,91 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "numbers.h"
|
||||
#include "bintree.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
105
test_binary.c
Normal file
105
test_binary.c
Normal file
@ -0,0 +1,105 @@
|
||||
#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();
|
||||
}
|
||||
61
test_numbers.c
Normal file
61
test_numbers.c
Normal file
@ -0,0 +1,61 @@
|
||||
#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();
|
||||
}
|
||||
@ -41,13 +41,13 @@ void test_deleteTopElement(void) {
|
||||
stack = push(stack, &testInts[i]);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_PTR(&testInts[2], top(stack));
|
||||
TEST_ASSERT_EQUAL_PTR(&testInts[2], stack->data);
|
||||
|
||||
stack = pop(stack);
|
||||
TEST_ASSERT_EQUAL_PTR(&testInts[1], top(stack));
|
||||
TEST_ASSERT_EQUAL_PTR(&testInts[1], stack->data);
|
||||
|
||||
stack = pop(stack);
|
||||
TEST_ASSERT_EQUAL_PTR(&testInts[0], top(stack));
|
||||
TEST_ASSERT_EQUAL_PTR(&testInts[0], stack->data);
|
||||
|
||||
stack = pop(stack);
|
||||
TEST_ASSERT_NULL(stack);
|
||||
@ -98,7 +98,7 @@ int main(void) {
|
||||
|
||||
UNITY_BEGIN();
|
||||
|
||||
printf("------------------------stack test------------------------\n");
|
||||
printf("\n------------------------stack test------------------------\n\n");
|
||||
|
||||
RUN_TEST(test_createNode);
|
||||
RUN_TEST(test_pushDataToStack);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user