Compare commits

..
1 Commits
7 changed files with 47 additions and 319 deletions
+8 -136
View File
@@ -10,155 +10,27 @@
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates // Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). // if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{
// Hilfsfunktion: neuen Knoten erstellen und Daten kopieren
static TreeNode* createNode(const void* data, size_t dataSize)
{
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
if (node == NULL)
{
return NULL;
} }
node->data = malloc(dataSize); // 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.
if (node->data == NULL) // 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.
free(node);
return NULL;
}
memcpy(node->data, data, dataSize);
// dataSize wird NICHT im struct gespeichert, da es nicht im Header ist
node->left = NULL;
node->right = NULL;
return node;
}
// Fügt eine Kopie der Daten in den Baum ein (rekursiv)
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
CompareFctType compareFct, int *isDuplicate)
{
// Basisfall: leerer Baum oder Blattknoten erreicht
if (root == NULL)
{
// isDuplicate auf 0 setzen, wenn nicht NULL
if (isDuplicate != NULL)
{
*isDuplicate = 0;
}
return createNode(data, dataSize);
}
// Daten vergleichen
int result = compareFct(data, root->data);
if (result < 0)
{
// Daten sind kleiner -> in linken Teilbaum einfügen
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else if (result > 0)
{
// Daten sind größer -> in rechten Teilbaum einfügen
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
else
{
// result == 0 → Duplikat gefunden
if (isDuplicate != NULL)
{
*isDuplicate = 1; // Duplikat, nicht einfügen
}
else
{
// Duplikate sind erlaubt -> in rechten Teilbaum einfügen
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
}
return root;
}
// Statischer Stack für die Iterator-Funktion (wie bei strtok)
static StackNode *iteratorStack = NULL;
// Iteriert über den Baum (In-Order-Traversierung mit Stack)
// Funktioniert wie strtok: beim ersten Aufruf root übergeben, dann NULL
void *nextTreeData(TreeNode *root) void *nextTreeData(TreeNode *root)
{ {
// Wenn root != NULL: neuer Iterator-Durchlauf starten
if (root != NULL)
{
// Alten Stack löschen, falls vorhanden
clearStack(iteratorStack);
iteratorStack = NULL;
// Alle linken Knoten auf den Stack pushen (bis zum kleinsten Element)
TreeNode *current = root;
while (current != NULL)
{
iteratorStack = push(iteratorStack, current);
current = current->left;
}
} }
// Wenn Stack leer ist, sind wir fertig // Releases all memory resources (including data copies).
if (iteratorStack == NULL)
{
return NULL;
}
// Oberstes Element vom Stack holen
TreeNode *node = (TreeNode *)top(iteratorStack);
iteratorStack = pop(iteratorStack);
// Wenn der Knoten einen rechten Teilbaum hat,
// alle linken Knoten des rechten Teilbaums auf den Stack pushen
if (node->right != NULL)
{
TreeNode *current = node->right;
while (current != NULL)
{
iteratorStack = push(iteratorStack, current);
current = current->left;
}
}
// Daten des aktuellen Knotens zurückgeben
return node->data;
}
// Gibt den gesamten Baum frei (rekursiv, Post-Order)
void clearTree(TreeNode *root) void clearTree(TreeNode *root)
{ {
if (root == NULL)
{
return; // Basisfall: leerer Teilbaum
} }
// Erst linken Teilbaum löschen // Returns the number of entries in the tree given by root.
clearTree(root->left);
// Dann rechten Teilbaum löschen
clearTree(root->right);
// Dann Daten und Knoten selbst löschen
free(root->data);
// Knoten selbst freigeben
free(root);
}
// Zählt die Knoten im Baum (rekursiv)
unsigned int treeSize(const TreeNode *root) unsigned int treeSize(const TreeNode *root)
{ {
if (root == NULL)
{
return 0; // Basisfall: leerer Teilbaum
}
// Rekursiv: Größe = 1 (aktueller Knoten) + linker Teilbaum + rechter Teilbaum
return 1 + treeSize(root->left) + treeSize(root->right);
} }
+3 -4
View File
@@ -7,10 +7,9 @@ typedef int (*CompareFctType)(const void *arg1, const void *arg2);
typedef struct node typedef struct node
{ {
void *data; // Zeiger auf die Daten void *data;
size_t dataSize; // ← NEU: Größe der Daten struct node *left;
struct node *left; // Linker Teilbaum struct node *right;
struct node *right; // Rechter Teilbaum
} TreeNode; } TreeNode;
// 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
-4
View File
@@ -1,5 +1 @@
manu;9959
manu;9949
player2;9925
manu;4983
player1;3999 player1;3999
+2 -3
View File
@@ -37,14 +37,13 @@ $(program_obj_filesobj_files): %.o: %.c
# -------------------------- # --------------------------
unitTests: unitTests:
$(CC) $(FLAGS) $^ -o test_stack test_stack.c stack.c -Wall && ./test_stack $(CC) $(FLAGS) $^ -o test_stack test_stack.c stack.c -Wall && ./test_stack
$(CC) $(FLAGS) $^ -o test_numbers test_numbers.c numbers.c bintree.c stack.c -Wall && ./test_numbers
# -------------------------- # --------------------------
# Clean # Clean
# -------------------------- # --------------------------
clean: clean:
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
del /f *.o doble test_stack test_numbers del /f *.o doble test_stack
else else
rm -f *.o doble test_stack test_numbers rm -f *.o doble test_stack
endif endif
+26 -104
View File
@@ -5,18 +5,6 @@
#include "numbers.h" #include "numbers.h"
#include "bintree.h" #include "bintree.h"
// Vergleichsfunktion für unsigned int (für Binärbaum und qsort)
static int compareUnsignedInt(const void *a, const void *b)
{
unsigned int valA = *(unsigned int *)a;
unsigned int valB = *(unsigned int *)b;
if (valA < valB) return -1;
if (valA > valB) return 1;
return 0;
}
// TODO: getDuplicate und createNumbers implementieren // TODO: getDuplicate und createNumbers implementieren
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. /* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen. * Sicherstellen, dass beim Befüllen keine Duplikate entstehen.
@@ -26,110 +14,44 @@ static int compareUnsignedInt(const void *a, const void *b)
// 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.
// Erzeugt ein Array mit len eindeutigen Zufallszahlen zwischen 1 und 2*len
// Verwendet Binärbaum zur Duplikatsvermeidung
// Gibt dann eine zufällige Zahl doppelt zurück
unsigned int *createNumbers(unsigned int len) unsigned int *createNumbers(unsigned int len)
{ {
// Eingabevalidierung
if (len == 0) int n;
printf("Wie viele Zufallszahlen sollen erstellt werden? ");
scanf("%d", &n);
int array[n];
srand(time(NULL)); // Zufallsgenerator initialisieren
for (int i = 0; i < n; i++)
{ {
return NULL; int zahl;
} char vorhanden;
// Array allokieren
unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int));
if (numbers == NULL)
{
return NULL;
}
// Binärbaum zur Duplikatsprüfung erstellen
TreeNode *tree = NULL;
// Zufallsgenerator initialisieren
static int seedInitialized = 0;
if (!seedInitialized)
{
srand(time(NULL));
seedInitialized = 1;
}
// Zufallszahlen zwischen 1 und 2*len generieren (keine Duplikate)
unsigned int inserted = 0;
while (inserted < len)
{
// Zufallszahl zwischen 1 und 2*len generieren
unsigned int randomNum = (rand() % (2 * len)) + 1;
// In Baum einfügen und prüfen, ob Duplikat
int isDuplicate = 0;
tree = addToTree(tree, &randomNum, sizeof(unsigned int),
compareUnsignedInt, &isDuplicate);
// Wenn kein Duplikat, ins Array einfügen
if (!isDuplicate)
{
numbers[inserted] = randomNum;
inserted++;
}
}
// Baum aufräumen
clearTree(tree);
// Einen zufälligen Eintrag duplizieren
// Wähle zwei verschiedene Indizes
unsigned int sourceIndex = rand() % len;
unsigned int targetIndex;
do do
{ {
targetIndex = rand() % len; vorhanden = 0;
} while (targetIndex == sourceIndex); zahl = rand() % n; // Zufallszahl zwischen 1 und 100
// Kopiere Wert von source nach target (erzeugt Duplikat) // Prüfen, ob Zahl schon im Array existiert
numbers[targetIndex] = numbers[sourceIndex]; for (int j = 0; j < i; j++)
return numbers;
}
// Findet das Duplikat durch Sortieren und Vergleich benachbarter Elemente
// Gibt 0 bei Fehlern zurück
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
{ {
// Eingabevalidierung if (array[j] == zahl)
if (numbers == NULL || len < 2)
{ {
return 0; // Fehler vorhanden = 1;
}
// Kopie des Arrays erstellen (um Original nicht zu verändern)
unsigned int *sortedNumbers = (unsigned int *)malloc(len * sizeof(unsigned int));
if (sortedNumbers == NULL)
{
return 0; // Speicherfehler
}
// Array kopieren
memcpy(sortedNumbers, numbers, len * sizeof(unsigned int));
// Array mit qsort sortieren
qsort(sortedNumbers, len, sizeof(unsigned int), compareUnsignedInt);
// Benachbarte Elemente vergleichen, um Duplikat zu finden
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++)
{
if (sortedNumbers[i] == sortedNumbers[i + 1])
{
duplicate = sortedNumbers[i];
break; break;
} }
} }
} while (vorhanden); // solange wiederholen, bis Zahl einzigartig ist
// Aufräumen array[i] = zahl;
free(sortedNumbers); }
return duplicate; 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)
{
} }
-60
View File
@@ -1,60 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "stack.h"
#include "numbers.h"
int main()
{
printf("=== Test createNumbers & getDuplicate ===\n\n");
unsigned int len = 10;
unsigned int *numbers = createNumbers(len);
if (numbers == NULL)
{
printf("Fehler: createNumbers() gab NULL zurück\n");
return 1;
}
printf("Generierte Zahlen: ");
for (unsigned int i = 0; i < len; i++)
{
printf("%u ", numbers[i]);
}
printf("\n\n");
unsigned int duplicate = getDuplicate(numbers, len);
if (duplicate == 0)
{
printf("Fehler: Kein Duplikat gefunden\n");
}
else
{
printf("Gefundenes Duplikat: %u\n", duplicate);
// Prüfen, ob es wirklich zweimal vorkommt
int count = 0;
for (unsigned int i = 0; i < len; i++)
{
if (numbers[i] == duplicate)
{
count++;
}
}
printf("Anzahl Vorkommen: %d\n", count);
if (count == 2)
{
printf("\n[PASSED] Test erfolgreich!\n");
}
else
{
printf("\n[FAILED] Duplikat kommt %d mal vor (erwartet: 2)\n", count);
}
}
free(numbers);
return 0;
}
+1 -1
View File
@@ -175,7 +175,7 @@ int main()
test_pushAndTop(); test_pushAndTop();
test_multiplePush(); test_multiplePush();
test_pushAndPop(); test_pushAndPop();
/*test_clearStack();*/ test_clearStack();
/*test_stressTest();*/ /*test_stressTest();*/
printf("\n=== Alle Tests abgeschlossen ===\n"); printf("\n=== Alle Tests abgeschlossen ===\n");