Compare commits
54 Commits
branchjens
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 07796c1390 | |||
|
|
25da0d20df | ||
| 6586a25fdb | |||
| 6e233b6695 | |||
| a01aa986e6 | |||
|
|
aae75ade4b | ||
|
|
5d976c50c1 | ||
| 92fa60f9dc | |||
| 284cdbdcfb | |||
| e3501e8550 | |||
| 6a9461bf5b | |||
| ef3e0b7891 | |||
| 82b2fb283f | |||
| 602220ba21 | |||
| 2368c9f3b9 | |||
| e4a8afabdd | |||
| 9d08970513 | |||
| 9ee0f9e281 | |||
| 21aa67b165 | |||
| 2d6f8689f2 | |||
| 8754182f79 | |||
| 144648886f | |||
| 748fd0d087 | |||
| 72f1d080a0 | |||
|
|
a6c5060060 | ||
| 02e008c03a | |||
|
|
2689130b55 | ||
| 7c3df62d86 | |||
| f7549910eb | |||
| 14fa122f20 | |||
| 1c10994396 | |||
| 402604cb45 | |||
| 5dc45f8590 | |||
| 6b30677698 | |||
| d56a2f7a03 | |||
| 36ac0d6d9d | |||
| 517d363f3e | |||
| f91ab68a72 | |||
| 574ed71bae | |||
| c49a8d687c | |||
| 42b83afec0 | |||
| b138a8f251 | |||
| ffde7270db | |||
| 409afc165b | |||
| 4042a7d979 | |||
| 1ead9595ce | |||
| e523b5462d | |||
| b50bd58dac | |||
| 2176383f1e | |||
| e52da066fa | |||
| 494fa2237c | |||
| 7dca38c37f | |||
| 03495bddf0 | |||
| 1763ac1f6d |
18
.vscode/c_cpp_properties.json
vendored
Normal file
18
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "macos-clang-arm64",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"compilerPath": "/usr/bin/clang",
|
||||||
|
"cStandard": "${default}",
|
||||||
|
"cppStandard": "${default}",
|
||||||
|
"intelliSenseMode": "macos-clang-arm64",
|
||||||
|
"compilerArgs": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
13
.vscode/launch.json
vendored
Normal file
13
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "C/C++ Runner: Debug Session",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "/Users/florianwetzel/I2_Praktikum/DobleSpiel",
|
||||||
|
"program": "/Users/florianwetzel/I2_Praktikum/DobleSpiel/build/Debug/outDebug"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
59
.vscode/settings.json
vendored
Normal file
59
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"C_Cpp_Runner.cCompilerPath": "clang",
|
||||||
|
"C_Cpp_Runner.cppCompilerPath": "clang++",
|
||||||
|
"C_Cpp_Runner.debuggerPath": "lldb",
|
||||||
|
"C_Cpp_Runner.cStandard": "",
|
||||||
|
"C_Cpp_Runner.cppStandard": "",
|
||||||
|
"C_Cpp_Runner.msvcBatchPath": "",
|
||||||
|
"C_Cpp_Runner.useMsvc": false,
|
||||||
|
"C_Cpp_Runner.warnings": [
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Wpedantic",
|
||||||
|
"-Wshadow",
|
||||||
|
"-Wformat=2",
|
||||||
|
"-Wcast-align",
|
||||||
|
"-Wconversion",
|
||||||
|
"-Wsign-conversion",
|
||||||
|
"-Wnull-dereference"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.msvcWarnings": [
|
||||||
|
"/W4",
|
||||||
|
"/permissive-",
|
||||||
|
"/w14242",
|
||||||
|
"/w14287",
|
||||||
|
"/w14296",
|
||||||
|
"/w14311",
|
||||||
|
"/w14826",
|
||||||
|
"/w44062",
|
||||||
|
"/w44242",
|
||||||
|
"/w14905",
|
||||||
|
"/w14906",
|
||||||
|
"/w14263",
|
||||||
|
"/w44265",
|
||||||
|
"/w14928"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.enableWarnings": true,
|
||||||
|
"C_Cpp_Runner.warningsAsError": false,
|
||||||
|
"C_Cpp_Runner.compilerArgs": [],
|
||||||
|
"C_Cpp_Runner.linkerArgs": [],
|
||||||
|
"C_Cpp_Runner.includePaths": [],
|
||||||
|
"C_Cpp_Runner.includeSearch": [
|
||||||
|
"*",
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.excludeSearch": [
|
||||||
|
"**/build",
|
||||||
|
"**/build/**",
|
||||||
|
"**/.*",
|
||||||
|
"**/.*/**",
|
||||||
|
"**/.vscode",
|
||||||
|
"**/.vscode/**"
|
||||||
|
],
|
||||||
|
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||||
|
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||||
|
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||||
|
"C_Cpp_Runner.showCompilationTime": false,
|
||||||
|
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||||
|
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||||
|
}
|
||||||
227
bintree.c
227
bintree.c
@ -1,36 +1,249 @@
|
|||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
#include "bintree.h"
|
#include "bintree.h"
|
||||||
|
|
||||||
|
|
||||||
//TODO: binären Suchbaum implementieren
|
//TODO: binären Suchbaum implementieren
|
||||||
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
|
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), Done
|
||||||
* `clearTree`: gibt den gesamten Baum frei (rekursiv),
|
* `clearTree`: gibt den gesamten Baum frei (rekursiv), Done
|
||||||
* `treeSize`: zählt die Knoten im Baum (rekursiv),
|
* `treeSize`: zählt die Knoten im Baum (rekursiv), Done
|
||||||
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
|
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. Done */
|
||||||
|
|
||||||
|
|
||||||
|
static StackNode *stackRoot = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
TreeNode *addToTree (TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate);
|
||||||
|
void *nextTreeData (TreeNode *root);
|
||||||
|
void clearTree (TreeNode *root);
|
||||||
|
unsigned int treeSize (const TreeNode *root);
|
||||||
|
|
||||||
|
// self declared functions
|
||||||
|
TreeNode *addToTreeRec (TreeNode *currentNode, TreeNode *newNode, CompareFctType compareFct, int *isDuplicate, const int root);
|
||||||
|
void clearTreeRec (TreeNode *currentNode);
|
||||||
|
void clearNode (TreeNode *node);
|
||||||
|
int treeSizeRec (const TreeNode *currentNode);
|
||||||
|
void *nextTreeDataRec (TreeNode *node, StackNode *stack);
|
||||||
|
|
||||||
|
|
||||||
// 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).
|
||||||
|
|
||||||
|
// returned Value is new root
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
// create a node
|
||||||
|
TreeNode *newNode;
|
||||||
|
|
||||||
|
|
||||||
|
newNode = calloc(1, sizeof(TreeNode));
|
||||||
|
newNode->data = calloc(1, dataSize);
|
||||||
|
newNode->left = NULL;
|
||||||
|
newNode->right = NULL;
|
||||||
|
memcpy(newNode->data, data, dataSize);
|
||||||
|
|
||||||
|
|
||||||
|
return addToTreeRec(root, newNode, compareFct, isDuplicate, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TreeNode *addToTreeRec(TreeNode *currentNode, TreeNode *newNode, CompareFctType compareFct, int *isDuplicate, const int root)
|
||||||
|
{
|
||||||
|
/*if ((currentNode == NULL))
|
||||||
|
{
|
||||||
|
if ((isDuplicate == NULL) || root)
|
||||||
|
{
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Mögliche Ergänzung --------------------------
|
||||||
|
if (currentNode == NULL)
|
||||||
|
{
|
||||||
|
if (isDuplicate != NULL)
|
||||||
|
*isDuplicate = 0;
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
else if ((compareFct(currentNode->data, newNode->data) < 0))
|
||||||
|
{
|
||||||
|
currentNode->left = addToTreeRec(currentNode->left, newNode, compareFct, isDuplicate, 0);
|
||||||
|
}
|
||||||
|
else if ((compareFct(currentNode->data, newNode->data) > 0))
|
||||||
|
{
|
||||||
|
currentNode->right = addToTreeRec(currentNode->right, newNode, compareFct, isDuplicate, 0);
|
||||||
|
}
|
||||||
|
else if ((compareFct(currentNode->data, newNode->data) == 0))
|
||||||
|
{
|
||||||
|
if (isDuplicate == NULL)
|
||||||
|
{
|
||||||
|
currentNode->left = addToTreeRec(currentNode->left, newNode, compareFct, isDuplicate, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*isDuplicate = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return currentNode;
|
||||||
|
} */
|
||||||
|
|
||||||
|
TreeNode *addToTreeRec(TreeNode *currentNode, TreeNode *newNode, CompareFctType compareFct, int *isDuplicate, const int root)
|
||||||
|
{
|
||||||
|
if ((currentNode == NULL))
|
||||||
|
{
|
||||||
|
if ((isDuplicate == NULL) || root)
|
||||||
|
{
|
||||||
|
if (isDuplicate != NULL)
|
||||||
|
{
|
||||||
|
*isDuplicate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*isDuplicate = 0;
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((compareFct(currentNode->data, newNode->data) < 0))
|
||||||
|
{
|
||||||
|
currentNode->left = addToTreeRec(currentNode->left, newNode, compareFct, isDuplicate, 0);
|
||||||
|
}
|
||||||
|
else if ((compareFct(currentNode->data, newNode->data) > 0))
|
||||||
|
{
|
||||||
|
currentNode->right = addToTreeRec(currentNode->right, newNode, compareFct, isDuplicate, 0);
|
||||||
|
}
|
||||||
|
else if ((compareFct(currentNode->data, newNode->data) == 0))
|
||||||
|
{
|
||||||
|
if (isDuplicate == NULL)
|
||||||
|
{
|
||||||
|
currentNode->left = addToTreeRec(currentNode->left, newNode, compareFct, isDuplicate, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*isDuplicate = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDuplicate != NULL)
|
||||||
|
{
|
||||||
|
*isDuplicate = 0;
|
||||||
|
}
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
||||||
|
// Needs stack!!
|
||||||
|
// Stack functions: push(), pop(), top(), clearStack()
|
||||||
void *nextTreeData(TreeNode *root)
|
void *nextTreeData(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
void *pointerToReturn = NULL;
|
||||||
|
|
||||||
|
if (root != NULL)
|
||||||
|
{
|
||||||
|
// Add tree to stack so that bigest entry is ontop
|
||||||
|
stackRoot = nextTreeDataRec(root, stackRoot);
|
||||||
|
pointerToReturn = stackRoot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// return current top entry and then pop that top entry
|
||||||
|
pointerToReturn = top(stackRoot);
|
||||||
|
stackRoot = pop(stackRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return pointerToReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *nextTreeDataRec(TreeNode *tree, StackNode *stack)
|
||||||
|
{
|
||||||
|
if (tree != NULL)
|
||||||
|
{
|
||||||
|
stack = nextTreeDataRec (tree->left, stack);
|
||||||
|
stack = push (stack, tree->data);
|
||||||
|
stack = nextTreeDataRec (tree->right, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Releases all memory resources (including data copies).
|
// Releases all memory resources (including data copies).
|
||||||
void clearTree(TreeNode *root)
|
void clearTree(TreeNode *root)
|
||||||
{
|
{
|
||||||
|
clearTreeRec(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void clearTreeRec(TreeNode *currentNode)
|
||||||
|
{
|
||||||
|
if (currentNode != NULL)
|
||||||
|
{
|
||||||
|
clearTree(currentNode->left);
|
||||||
|
clearTree(currentNode->right);
|
||||||
|
clearNode(currentNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void clearNode(TreeNode *node)
|
||||||
|
{
|
||||||
|
free(node->data);
|
||||||
|
node->data = NULL;
|
||||||
|
|
||||||
|
node->left = NULL;
|
||||||
|
node->right = NULL;
|
||||||
|
|
||||||
|
free(node);
|
||||||
|
node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
|
unsigned int amountOfNodes = 0;
|
||||||
|
|
||||||
|
|
||||||
|
amountOfNodes = treeSizeRec(root);
|
||||||
|
|
||||||
|
|
||||||
|
return amountOfNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int treeSizeRec(const TreeNode *currentNode)
|
||||||
|
{
|
||||||
|
int nodeCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (currentNode != NULL)
|
||||||
|
{
|
||||||
|
nodeCount += treeSizeRec(currentNode->left);
|
||||||
|
nodeCount += treeSizeRec(currentNode->right);
|
||||||
|
return nodeCount + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeCount;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
223
bintreeTests.c
Normal file
223
bintreeTests.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "bintree.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#define MAX_TEST_NAME_LEN 10
|
||||||
|
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int compareIntEntries(const void *arg1, const void *arg2)
|
||||||
|
{
|
||||||
|
const int *entry1 = (const void *)arg1;
|
||||||
|
const int *entry2 = (const void *)arg2;
|
||||||
|
|
||||||
|
int result = *entry2 - *entry1;
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// test if addToTree expands tree correctly
|
||||||
|
// by going down the path where the given pice of data is expected
|
||||||
|
// and checking if the pice of data is found there
|
||||||
|
void test_addToTreeExpandsTreeCorrectly(void)
|
||||||
|
{
|
||||||
|
TreeNode *testRoot = NULL;
|
||||||
|
int testIsDouble = 0;
|
||||||
|
int score1 = 12;
|
||||||
|
int score2 = 6;
|
||||||
|
int score3 = 18;
|
||||||
|
int score4 = 3;
|
||||||
|
int score5 = 9;
|
||||||
|
int score6 = 15;
|
||||||
|
int score7 = 21;
|
||||||
|
|
||||||
|
|
||||||
|
testRoot = addToTree(testRoot, &score1, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score2, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score3, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score4, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score5, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score6, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score7, sizeof(int), compareIntEntries, NULL);
|
||||||
|
|
||||||
|
// Checking the Tree without Doubles
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot);
|
||||||
|
TEST_ASSERT_EQUAL(score1, *(int *)testRoot->data);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->left);
|
||||||
|
TEST_ASSERT_EQUAL(score2, *(int *)testRoot->left->data);
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->right);
|
||||||
|
TEST_ASSERT_EQUAL(score3, *(int *)testRoot->right->data);
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->left->left);
|
||||||
|
TEST_ASSERT_EQUAL(score4, *(int *)testRoot->left->left->data);
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->left->right);
|
||||||
|
TEST_ASSERT_EQUAL(score5, *(int *)testRoot->left->right->data);
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->right->left);
|
||||||
|
TEST_ASSERT_EQUAL(score6, *(int *)testRoot->right->left->data);
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->right->right);
|
||||||
|
TEST_ASSERT_EQUAL(score7, *(int *)testRoot->right->right->data);
|
||||||
|
|
||||||
|
// Adding Double
|
||||||
|
testRoot = addToTree(testRoot, &score4, sizeof(int), compareIntEntries, NULL);
|
||||||
|
TEST_ASSERT_NOT_NULL(testRoot->left->left->left);
|
||||||
|
TEST_ASSERT_EQUAL_UINT16(score4, *(int *)testRoot->left->left->left->data);
|
||||||
|
|
||||||
|
// Trying to add Double while Doubles not Permitted
|
||||||
|
testRoot = addToTree(testRoot, &score7, sizeof(int), compareIntEntries, &testIsDouble);
|
||||||
|
TEST_ASSERT_NULL(testRoot->right->right->left);
|
||||||
|
TEST_ASSERT_EQUAL_UINT16(1, testIsDouble);
|
||||||
|
|
||||||
|
|
||||||
|
clearTree(testRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// test if nextTreeData returns the next pice of data correctly
|
||||||
|
// needs Stack!!!
|
||||||
|
void test_nextTreeDataReturnsNextDataCorrectly(void)
|
||||||
|
{
|
||||||
|
TreeNode *testRoot = NULL;
|
||||||
|
int score1 = 12;
|
||||||
|
int score2 = 6;
|
||||||
|
int score3 = 18;
|
||||||
|
int score4 = 3;
|
||||||
|
int score5 = 9;
|
||||||
|
int score6 = 15;
|
||||||
|
int score7 = 21;
|
||||||
|
|
||||||
|
|
||||||
|
// Prepare a Tree
|
||||||
|
testRoot = addToTree(testRoot, &score1, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score2, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score3, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score4, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score5, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score6, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score7, sizeof(int), compareIntEntries, NULL);
|
||||||
|
|
||||||
|
// Create Stack
|
||||||
|
StackNode *entry = nextTreeData(testRoot);
|
||||||
|
|
||||||
|
// check if nextTreeData returns Data correctly
|
||||||
|
TEST_ASSERT_NOT_NULL(entry);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(score7, *(int *)nextTreeData(NULL));
|
||||||
|
TEST_ASSERT_EQUAL(score3, *(int *)nextTreeData(NULL));
|
||||||
|
TEST_ASSERT_EQUAL(score6, *(int *)nextTreeData(NULL));
|
||||||
|
TEST_ASSERT_EQUAL(score1, *(int *)nextTreeData(NULL));
|
||||||
|
TEST_ASSERT_EQUAL(score5, *(int *)nextTreeData(NULL));
|
||||||
|
TEST_ASSERT_EQUAL(score2, *(int *)nextTreeData(NULL));
|
||||||
|
TEST_ASSERT_EQUAL(score4, *(int *)nextTreeData(NULL));
|
||||||
|
|
||||||
|
|
||||||
|
clearTree(testRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// test if clear Tree frees all node.name and node memory AND sets them to zero
|
||||||
|
// aditionally tests if the memoryspaces have been cleared
|
||||||
|
void test_clearTreeworksLikeExpected(void)
|
||||||
|
{
|
||||||
|
TreeNode *testRoot = NULL;
|
||||||
|
int score1 = 12;
|
||||||
|
int score2 = 6;
|
||||||
|
int score3 = 18;
|
||||||
|
int score4 = 3;
|
||||||
|
int score5 = 9;
|
||||||
|
int score6 = 15;
|
||||||
|
int score7 = 21;
|
||||||
|
|
||||||
|
|
||||||
|
testRoot = addToTree(testRoot, &score1, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score2, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score3, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score4, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score5, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score6, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score7, sizeof(int), compareIntEntries, NULL);
|
||||||
|
|
||||||
|
// Save all Adresses
|
||||||
|
TreeNode *node1 = testRoot;
|
||||||
|
TreeNode *node2 = testRoot->left;
|
||||||
|
TreeNode *node3 = testRoot->left->left;
|
||||||
|
TreeNode *node4 = testRoot->left->right;
|
||||||
|
TreeNode *node5 = testRoot->right;
|
||||||
|
TreeNode *node6 = testRoot->right->left;
|
||||||
|
TreeNode *node7 = testRoot->right->right;
|
||||||
|
|
||||||
|
clearTree(testRoot);
|
||||||
|
|
||||||
|
// Check if everything has been set to NULL
|
||||||
|
TEST_ASSERT_NULL(node1->data);
|
||||||
|
TEST_ASSERT_NULL(node1->data);
|
||||||
|
TEST_ASSERT_NULL(node2->data);
|
||||||
|
TEST_ASSERT_NULL(node3->data);
|
||||||
|
TEST_ASSERT_NULL(node4->data);
|
||||||
|
TEST_ASSERT_NULL(node5->data);
|
||||||
|
TEST_ASSERT_NULL(node6->data);
|
||||||
|
TEST_ASSERT_NULL(node7->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// tests if treeSize returns correct amount of nodes in Tree
|
||||||
|
// by using addToTree a given number of times and testing to see if
|
||||||
|
// the treeSize matches the number of nodes added
|
||||||
|
void test_treeSizeWorkingLikeExpected(void)
|
||||||
|
{
|
||||||
|
TreeNode *testRoot = NULL;
|
||||||
|
int nodeCount = 7;
|
||||||
|
unsigned int testTreeSize = 0;
|
||||||
|
int score1 = 12;
|
||||||
|
int score2 = 6;
|
||||||
|
int score3 = 18;
|
||||||
|
int score4 = 3;
|
||||||
|
int score5 = 9;
|
||||||
|
int score6 = 15;
|
||||||
|
int score7 = 21;
|
||||||
|
|
||||||
|
|
||||||
|
// Fill Tree
|
||||||
|
testRoot = addToTree(testRoot, &score1, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score2, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score3, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score4, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score5, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score6, sizeof(int), compareIntEntries, NULL);
|
||||||
|
testRoot = addToTree(testRoot, &score7, sizeof(int), compareIntEntries, NULL);
|
||||||
|
|
||||||
|
testTreeSize = treeSize(testRoot);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(nodeCount, testTreeSize);
|
||||||
|
|
||||||
|
clearTree(testRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// main, strings together all tests
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
printf("\n============================\nBinary Tree tests\n============================\n");
|
||||||
|
RUN_TEST(test_addToTreeExpandsTreeCorrectly);
|
||||||
|
RUN_TEST(test_nextTreeDataReturnsNextDataCorrectly);
|
||||||
|
RUN_TEST(test_clearTreeworksLikeExpected);
|
||||||
|
RUN_TEST(test_treeSizeWorkingLikeExpected);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
|
|
||||||
BIN
doble_initial.exe
Normal file
BIN
doble_initial.exe
Normal file
Binary file not shown.
@ -1,2 +1 @@
|
|||||||
player_name;9943
|
|
||||||
player1;3999
|
player1;3999
|
||||||
|
|||||||
15
makefile
15
makefile
@ -35,14 +35,25 @@ $(program_obj_filesobj_files): %.o: %.c
|
|||||||
# --------------------------
|
# --------------------------
|
||||||
# Unit Tests
|
# Unit Tests
|
||||||
# --------------------------
|
# --------------------------
|
||||||
unitTests:
|
# unitTests:
|
||||||
echo "needs to be implemented"
|
# echo "needs to be implemented"
|
||||||
|
|
||||||
|
bintree: bintree.c
|
||||||
|
$(CC) $(FLAGS) -c bintree bintree.c
|
||||||
|
|
||||||
|
bintreeTests: stack.o bintree.o bintreeTests.c $(unityfolder)/unity.c
|
||||||
|
$(CC) $(FLAGS) -o runbintreeTests bintreeTests.c bintree.o stack.o $(unityfolder)/unity.c
|
||||||
|
|
||||||
stack: stack.c
|
stack: stack.c
|
||||||
$(CC) $(FLAGS) -c stack stack.c
|
$(CC) $(FLAGS) -c stack stack.c
|
||||||
|
|
||||||
test_stack: stack.o test_stack.c $(unityfolder)/unity.c
|
test_stack: stack.o test_stack.c $(unityfolder)/unity.c
|
||||||
$(CC) $(FLAGS) -o runstackTests test_stack.c stack.o $(unityfolder)/unity.c
|
$(CC) $(FLAGS) -o runstackTests test_stack.c stack.o $(unityfolder)/unity.c
|
||||||
|
|
||||||
|
test_numbers: numbers.o bintree.o stack.o test_numbers.c $(unityfolder)/unity.c
|
||||||
|
$(CC) $(FLAGS) -o run_numbersTests test_numbers.c numbers.o bintree.o stack.o $(unityfolder)/unity.c
|
||||||
|
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Clean
|
# Clean
|
||||||
# --------------------------
|
# --------------------------
|
||||||
|
|||||||
93
numbers.c
93
numbers.c
@ -14,13 +14,106 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
static int compareUInt(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
unsigned int A = *(unsigned int*)a;
|
||||||
|
unsigned int B = *(unsigned int*)b;
|
||||||
|
if (A < B) return -1;
|
||||||
|
if (A > B) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Sortiervergleich für qsort
|
||||||
|
int compareQsort(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
unsigned int A = *(const unsigned int*)a;
|
||||||
|
unsigned int B = *(const unsigned int*)b;
|
||||||
|
if (A < B) return -1;
|
||||||
|
if (A > B) return +1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int *createNumbers(unsigned int len)
|
unsigned int *createNumbers(unsigned int len)
|
||||||
{
|
{
|
||||||
|
if (len < 2) return NULL;
|
||||||
|
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
|
||||||
|
// Speicher für das Array
|
||||||
|
unsigned int *numbers = malloc(sizeof(unsigned int) * len);
|
||||||
|
if (!numbers) return NULL;
|
||||||
|
|
||||||
|
TreeNode *root = NULL; // Baumwurzel
|
||||||
|
unsigned int value;
|
||||||
|
int isDuplicate;
|
||||||
|
|
||||||
|
//Array mit eindeutigen Zufallszahlen füllen
|
||||||
|
for (unsigned int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
value = (rand() % (2 * len)) + 1; // Zufallszahl 1..2*len
|
||||||
|
isDuplicate = 0;
|
||||||
|
|
||||||
|
TreeNode *newRoot = addToTree(
|
||||||
|
root,
|
||||||
|
&value,
|
||||||
|
sizeof(unsigned int),
|
||||||
|
compareUInt,
|
||||||
|
&isDuplicate
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isDuplicate)
|
||||||
|
{
|
||||||
|
// Neue Zahl - akzeptieren
|
||||||
|
root = newRoot;
|
||||||
|
numbers[i] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Sonst neue Zahl generieren
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//genau eine Zufallszahl duplizieren
|
||||||
|
unsigned int idx1 = rand() % len;
|
||||||
|
unsigned int idx2 = rand() % len;
|
||||||
|
|
||||||
|
while (idx2 == idx1)
|
||||||
|
idx2 = rand() % len;
|
||||||
|
|
||||||
|
numbers[idx2] = numbers[idx1];
|
||||||
|
|
||||||
|
// Baum wieder freigeben
|
||||||
|
clearTree(root);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
unsigned int *copy = malloc(len * sizeof(unsigned int));
|
||||||
|
if (!copy) return 0;
|
||||||
|
|
||||||
|
// Array kopieren
|
||||||
|
memcpy(copy, numbers, len * sizeof(unsigned int));
|
||||||
|
|
||||||
|
// Sortieren
|
||||||
|
qsort(copy, len, sizeof(unsigned int), compareQsort);
|
||||||
|
|
||||||
|
// Doppelte Zahl finden
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
BIN
run_numbersTests.exe
Normal file
BIN
run_numbersTests.exe
Normal file
Binary file not shown.
BIN
runbintreeTests.exe
Normal file
BIN
runbintreeTests.exe
Normal file
Binary file not shown.
BIN
runstackTests.exe
Normal file
BIN
runstackTests.exe
Normal file
Binary file not shown.
87
test_numbers.c
Normal file
87
test_numbers.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "numbers.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
// gehört zu unit-Grundaufbau
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
// gehört zu unit-Grundaufbau
|
||||||
|
}
|
||||||
|
|
||||||
|
// prüft, ob ein Array nur EIN Duplikat enthält
|
||||||
|
static int countDuplicates(const unsigned int *arr, unsigned int len) {
|
||||||
|
int count = 0;
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
for (unsigned int j = i + 1; j < len; j++) {
|
||||||
|
if (arr[i] == arr[j]) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfen, ob createNumbers ein korrektes Array liefert
|
||||||
|
static void test_createNumbers_basic(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 100;
|
||||||
|
unsigned int *arr = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(arr); // prüft ob Speicher korrekt
|
||||||
|
|
||||||
|
// Prüfen: Länge stimmt
|
||||||
|
|
||||||
|
// Prüfen: Array enthält GENAU EIN Duplikat
|
||||||
|
int dupCount = countDuplicates(arr, len);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, dupCount);
|
||||||
|
|
||||||
|
free(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEST 2: Prüfen, ob getDuplicate die richtige doppelte Zahl erkennt
|
||||||
|
static void test_getDuplicate_correctValue(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 200;
|
||||||
|
unsigned int *arr = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(arr);
|
||||||
|
|
||||||
|
unsigned int duplicate = getDuplicate(arr, len);
|
||||||
|
|
||||||
|
// Manuelle Kontrolle: Der gefundene Wert muss tatsächlich doppelt vorkommen
|
||||||
|
int occurrences = 0;
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
if (arr[i] == duplicate) {
|
||||||
|
occurrences++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(2, occurrences);
|
||||||
|
|
||||||
|
free(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEST 3: getDuplicate gibt 0 aus bei Fehlern
|
||||||
|
static void test_getDuplicate_errors(void)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(NULL, 10));
|
||||||
|
TEST_ASSERT_EQUAL_UINT(0, getDuplicate((unsigned int*)1, 1)); // len < 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testbereich
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(test_createNumbers_basic);
|
||||||
|
RUN_TEST(test_getDuplicate_correctValue);
|
||||||
|
RUN_TEST(test_getDuplicate_errors);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user