Compare commits

...
5 Commits
Author SHA1 Message Date
moehrleinai99137 06890682f8 Add unit test test_numbers.c 2025-11-28 14:58:12 +01:00
moehrleinai99137 a515698e0f Erweitern numbers.c 2025-11-28 14:39:41 +01:00
moehrleinai99137 a309d2dfc2 Änderung bintree.c 2025-11-28 14:10:26 +01:00
moehrleinai99137 2e93327ba5 Add unit test file test_stack.c 2025-11-28 13:23:20 +01:00
moehrleinai99137 833e93fa49 Add unit test file test_stack.c 2025-11-28 12:55:15 +01:00
4 changed files with 388 additions and 3 deletions

No files matched your search

+85 -2
View File
@@ -1,4 +1,4 @@
#include <string.h>
#include <string.h> // für memcpy
#include "stack.h"
#include "bintree.h"
@@ -11,8 +11,46 @@
// 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)
{
{
// 1. Leerer Baum → neuen Knoten anlegen
if (root == NULL) // Baum muss leer sein
{
TreeNode *node = malloc(sizeof(TreeNode)); // Speicherreservierung
if (!node) return NULL; //Abbruch wenn kein Speicher verfügbar
node->data = malloc(dataSize); // Speicher für Daten reservieren
if (!node->data) { // Bei Fehler -> freigeben des Knotens und abbrechen
free(node);
return NULL;
}
memcpy(node->data, data, dataSize); // Daten kopieren (nicht Zeiger)
node->left = node->right = NULL; // Neuer Knoten hat keine Kinder
if (isDuplicate) *isDuplicate = 0; // Rückmeldung (kein Duplikat)
return node;
}
// 2. Vergleich, um Einfügerichtung zu bestimmen
int cmp = compareFct(data, root->data);
if (cmp < 0) // kleiner nach links weitergeben (rekursiv)
{
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else if (cmp > 0) // größer nach rechts weitergeben
{
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
else
{
// Duplikat
if (isDuplicate) *isDuplicate = 1;
// wird nicht eingefügt (kein Änderung am Baum)
}
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.
@@ -20,17 +58,62 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc
// push the top node and push all its left nodes.
void *nextTreeData(TreeNode *root)
{
static StackNode *iterStack = NULL; // behält den Wert zw. Funktionsaufrufen (speichert welche Knoten noch besucht werden müssen)
// Wird ein neuer Baum übergeben?
if (root != NULL)
{
// alten Stack löschen
clearStack(iterStack);
iterStack = NULL;
// Root + alle linken Knoten auf Stack pushen
TreeNode *cur = root;
while (cur != NULL)
{
iterStack = push(iterStack, cur);
cur = cur->left;
}
}
// Kein Baum mehr → Besuchen aller Knoten beendet
if (iterStack == NULL)
return NULL;
// Top-Knoten (als nächstes Reihe)
TreeNode *node = (TreeNode *)top(iterStack);
iterStack = pop(iterStack); //entfernen des Knoten
// Rechtsknoten
TreeNode *right = node->right; //nach Besuch bei rechten Knoten in rechten Teilbaum
while (right != NULL)
{
iterStack = push(iterStack, right);
right = right->left; // von dort ganz nach links und alles pushen
}
return node->data;
}
// Releases all memory resources (including data copies).
void clearTree(TreeNode *root)
{
if (root == NULL) //Abbruchbedingung
return;
clearTree(root->left); // Links und rechts löschen
clearTree(root->right);
free(root->data); // Daten freigeben
free(root);
}
// Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root)
{
if (root == NULL) // Leerer Baum
return 0;
return 1 + treeSize(root->left) + treeSize(root->right);
// Größe = 1 + Größe links + Größe rechts
}
+75 -1
View File
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <time.h> // für Zufallszahlen
#include <string.h>
#include "numbers.h"
#include "bintree.h"
@@ -10,17 +10,91 @@
* 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. */
// Vergleichsfunktion für unsigned int
static int compareUInt(const void *a, const void *b)
{
unsigned int x = *(unsigned int *)a; // beide void Zeiger in unsigned int
unsigned int y = *(unsigned int *)b;
// Vergleich wie beim Binärbaum
if (x < y) return -1; // links
if (x > y) return 1; // rechts
return 0; // gleich
}
// 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) // min 2 Zahlen sind notwendig
return NULL;
// Erzeugen eines Arrays (unsigned int)
unsigned int *arr = malloc(sizeof(unsigned int) * len);
if (!arr)
return NULL; // kein Speicher -> Fehler
srand((unsigned int)time(NULL)); // Initialisieren Zufallszahl
TreeNode *root = NULL;
int isDup; // zeigt ob Duplikat
unsigned int count = 0;
// Erzeugen der Zufallszahlen
while (count < len - 1) // ERST len-1 verschiedene Zahlen (ein Platz übrig für Duplikat)
{
unsigned int value = (rand() % (2 * len)) + 1; // Bereich 1 bis 2len (wahrscheinlich wenig Duplikate)
root = addToTree(root, &value, sizeof(unsigned int), compareUInt, &isDup);
// Einfügen der Zahl in Binärbaum (isDup==0 neue Zahl ) (isDup==1 Zahl war schon)
if (!isDup) // nur hinzufügen, wenn kein Duplikat
{
arr[count] = value; //Neuer Wert gespeichert (Duplikate ignoriert)
count++;
}
}
// EIN zufälliges Duplikat hinzufügen
unsigned int idx = rand() % (len - 1);
arr[len - 1] = arr[idx];
clearTree(root); // Freigeben des Baumes
return arr; // Zurückgeben des Array
}
// 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) // Prüfen ob Array leer oder zu kurz
return 0;
// Kopie erstellen zum Sortieren
unsigned int *tmp = malloc(sizeof(unsigned int) * len);
if (!tmp)
return 0;
for (unsigned int i = 0; i < len; i++) // Werte kopieren
tmp[i] = numbers[i];
// Sortieren (qsort - Vergleichsfunktion)
qsort(tmp, len, sizeof(unsigned int), compareUInt);
// benachbarte Duplikate finden
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++) // Durchlaufen des Arrays
{
if (tmp[i] == tmp[i + 1]) // wenn 2 aufeinanderfolgende Werte gleich -> Duplikat
{
duplicate = tmp[i];
break;
}
}
free(tmp); // Kopie freigeben
return duplicate; //gefundene Zahl zurückgeben
}
+119
View File
@@ -0,0 +1,119 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> // Abbruch bei unerfüllter Bedingung
#include "numbers.h"
#include "bintree.h"
// Vergleichsfunktion für unsigned int (für BST-Test)
static int compareUInt(const void *a, const void *b) // nur in dieser Datei sichtbar
{
unsigned int x = *(const unsigned int *)a; // in unsigned in umwandeln
unsigned int y = *(const unsigned int *)b;
if (x < y) return -1; // Vergleichsrückgabe für Binärbaum
if (x > y) return 1;
return 0;
}
void test_createNumbers_basic()
{
printf("Running test_createNumbers_basic...\n");
unsigned int len = 20; // Anlegen eines Arrays
unsigned int *arr = createNumbers(len);
assert(arr != NULL); // Fehler -> Abbruch
assert(len >= 2); // für ein Duplikat min 2
// Prüfen: Array hat länge len
unsigned int size = len;
(void)size; // vermeidet warnings
free(arr); // Speicher wird freigegeben
printf(" test_createNumbers_basic passed\n");
}
void test_createNumbers_unique_except_one()
{
printf("Running test_createNumbers_unique_except_one...\n");
unsigned int len = 100; // Erzeugen eines Arrays
unsigned int *arr = createNumbers(len);
assert(arr != NULL);
// Prüfen, dass genau EIN Duplikat existiert
TreeNode *root = NULL; // neuer Binärbaum
int isDup; // zeigt ob Wert doppelt
unsigned int duplicateCount = 0; // zählt gefundene Duplikate
for (unsigned int i = 0; i < len; i++) // Array in BST eingefügt
{
root = addToTree(root, &arr[i], sizeof(unsigned int), compareUInt, &isDup);
if (isDup)
duplicateCount++; // sollte 1 sein
}
// Es muss genau 1 doppelter Wert existieren
assert(duplicateCount == 1);
clearTree(root); // Baum und Array freigeben
free(arr);
printf(" test_createNumbers_unique_except_one passed\n");
}
void test_getDuplicate()
{
printf("Running test_getDuplicate...\n");
unsigned int len = 50; // Erzeugen eines Arrays
unsigned int *arr = createNumbers(len);
assert(arr != NULL);
unsigned int duplicate = getDuplicate(arr, len); // soll Duplikat finden
unsigned int countInArray = 0;
for (unsigned int i = 0; i < len; i++) // Durchlauf des Arrays
{
if (arr[i] == duplicate)
countInArray++; // Zählt wie oft die gefundene Zahl vorkommt
}
assert(countInArray == 2); // alle anderen Werte einzigartig
free(arr); // Array freigeben
printf(" test_getDuplicate passed\n");
}
// Testet große Arrays (Stress-Test)
void test_large_input() // testes zufällige Kollision
{
printf("Running test_large_input...\n");
unsigned int len = 20000; // Erzeugen eines Arrays
unsigned int *arr = createNumbers(len);
assert(arr != NULL);
unsigned int d = getDuplicate(arr, len); // doppelter Wert sollte existieren
assert(d != 0);
free(arr); // Array freigeben
printf(" test_large_input passed\n");
}
int main()
{
printf("=== Running numbers Tests ===\n");
test_createNumbers_basic(); // alle Test nacheinander ausführen
test_createNumbers_unique_except_one();
test_getDuplicate();
test_large_input();
printf("=== All tests passed successfully! ===\n");
return 0;
}
+109
View File
@@ -0,0 +1,109 @@
#include <stdio.h>
#include <stdlib.h> // für malloc und free
#include <assert.h> // für assert() - Programm stoppt bei Fehlern
#include "stack.h"
// Hilfsfunktion: beendet Programm bei malloc-Fehler
int *make_int(int value)
{
int *p = malloc(sizeof(int)); //Reserviert Speicherplatz für eine Zahl und gibt dessen Adresse zurück
assert(p != NULL); // Programm stoppt wenn Speicher zu knapp
*p = value; // Speichert Wert in neuen Speicherplatz
return p; // Gibt Zeiger zurück
}
// Test: Push und Top.
void test_push_and_top()
{
printf("Running test_push_and_top...\n");
StackNode *stack = NULL; // Stack beginnt leer
int *a = make_int(10); // zwei Zeiger
int *b = make_int(20);
stack = push(stack, a); // Erst 10 auf Stack gelegt
stack = push(stack, b); // Dann 20 (oben)
int *topValue = (int *)top(stack); // Datentyp in int umgewandelt
assert(topValue != NULL); // Stack darf nicht leer sein
assert(*topValue == 20); // Kopf muss 20 sein
clearStack(stack); // Entfernt alle Knoten
free(a); // Löscht die Daten
free(b);
printf(" test_push_and_top passed\n");
}
// Test: Pop in korrekter Reihenfolge
void test_push_pop_sequence()
{
printf("Running test_push_pop_sequence...\n");
StackNode *stack = NULL; // Stack muss leer sein
int *a = make_int(1); // Definieren der Testwerte
int *b = make_int(2);
int *c = make_int(3);
stack = push(stack, a); // Werte auf den Stack legen (C oben)
stack = push(stack, b);
stack = push(stack, c);
// Pop 3
int *v = (int *)top(stack); //Top muss 3 sein
assert(*v == 3);
stack = pop(stack); // 3 entfernen
// Pop 2
v = (int *)top(stack); //analog zur 3
assert(*v == 2);
stack = pop(stack);
// Pop 1
v = (int *)top(stack);
assert(*v == 1);
stack = pop(stack);
// Stack sollte leer sein
assert(stack == NULL);
free(a); // Freigeben des Speichers
free(b);
free(c);
printf(" test_push_pop_sequence passed\n");
}
// Test: clearStack
void test_clearStack()
{
printf("Running test_clearStack...\n");
StackNode *stack = NULL; // Stack muss leer sein
for (int i = 0; i < 5; i++) // 5 Elemente auf dem Stack (O bis 4)
stack = push(stack, make_int(i));
clearStack(stack); //Knoten freigeben
// danach ist Stack nur als "gelöscht" markiert,
// aber Pointer ist nicht automatisch NULL → das prüft man so:
stack = NULL; //Stackzeiger manuell auf NULL setzen
printf(" test_clearStack passed\n");
}
int main()
{
printf("=== Running Stack Unit Tests ===\n");
test_push_and_top(); // Ausführen aller Tests
test_push_pop_sequence();
test_clearStack();
printf("=== All tests passed successfully! ===\n");
return 0;
}