This commit is contained in:
Sara Stark 2025-12-15 11:26:43 +01:00
parent cd4f74f9a5
commit bb8bd2ace8
2 changed files with 35 additions and 33 deletions

View File

@ -41,10 +41,10 @@ unsigned int *createNumbers(unsigned int len)
{ {
srand(time(NULL)); srand(time(NULL));
// Sicherheitscheck für len (Minimum 3, siehe main.c) // Sicherheitscheck für len (Minimum 3, da sonst kein Duplikat möglich ist)
if (len < 3) return NULL; if (len < 3) return NULL;
// Allokiere Speicher für 'len' unsigned int // Array auf dem Heap allokieren
unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int)); unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int));
if (numbers == NULL) if (numbers == NULL)
@ -53,23 +53,23 @@ unsigned int *createNumbers(unsigned int len)
return NULL; return NULL;
} }
// 2. Binären Suchbaum initialisieren // Binären Suchbaum initialisieren für Duplikatprüfung
TreeNode *treeRoot = NULL; TreeNode *treeRoot = NULL;
// Variablen für Schleife und Zufallszahl // Variablen für Schleife und Zufallszahl
unsigned int randomNumber; unsigned int randomNumber;
int isDuplicate; // Flag für addToTree int isDuplicate; // Flag von addToTree gesetzt
// Die Schleife läuft nur bis len - 1, da die letzte Zahl das Duplikat wird // Die Schleife läuft nur bis len - 1, da die letzte Zahl das Duplikat wird
for (unsigned int i = 0; i < len - 1; i++) for (unsigned int i = 0; i < len - 1; i++)
{ {
do do
{ {
// 3a. Zufallszahl generieren [1, 2 * len] // Zufallszahl generieren [1, 2 * len]
// Formel: (rand() % (Obergrenze - Untergrenze + 1)) + Untergrenze // Formel: (rand() % (Obergrenze - Untergrenze + 1)) + Untergrenze
randomNumber = (rand() % (2 * len)) + 1; randomNumber = (rand() % (2 * len)) + 1;
// 3b. Zahl in den Binärbaum einfügen (und Duplikat prüfen) // Zahl in den Binärbaum einfügen (und Duplikat prüfen)
// addToTree gibt treeRoot zurück, das wird für die nächste Iteration gespeichert. // addToTree gibt treeRoot zurück, das wird für die nächste Iteration gespeichert.
// isDuplicate wird auf 1 gesetzt, wenn die Zahl schon existiert. // isDuplicate wird auf 1 gesetzt, wenn die Zahl schon existiert.
treeRoot = addToTree( treeRoot = addToTree(
@ -89,11 +89,11 @@ unsigned int *createNumbers(unsigned int len)
} while (isDuplicate); // Solange eine Duplikat-Nummer generiert wurde, wiederhole. } while (isDuplicate); // Solange eine Duplikat-Nummer generiert wurde, wiederhole.
// 4. Eindeutige Zahl im Array speichern // Eindeutige Zahl im Array speichern
numbers[i] = randomNumber; numbers[i] = randomNumber;
} }
// 5. Duplikat erzeugen (letzter Eintrag des Arrays) // Duplikat erzeugen (letzter Eintrag des Arrays)
// Wähle einen zufälligen Index der bereits gefüllten eindeutigen Zahlen [0, len - 2] // Wähle einen zufälligen Index der bereits gefüllten eindeutigen Zahlen [0, len - 2]
// Wir wählen aus den len-1 bereits gefüllten Einträgen. // Wir wählen aus den len-1 bereits gefüllten Einträgen.
@ -102,7 +102,7 @@ unsigned int *createNumbers(unsigned int len)
// Kopiere den Wert des zufälligen Index auf das letzte Element // Kopiere den Wert des zufälligen Index auf das letzte Element
numbers[len - 1] = numbers[duplicateIndex]; numbers[len - 1] = numbers[duplicateIndex];
// 6. Aufräumen: Speicher des Binärbaums freigeben (sehr wichtig!) // Speicher des Binärbaums freigeben (sehr wichtig!)
// Voraussetzung: clearTree ist in bintree.c implementiert. // Voraussetzung: clearTree ist in bintree.c implementiert.
clearTree(treeRoot); clearTree(treeRoot);
@ -114,10 +114,13 @@ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
{ {
unsigned int duplicate = 0; // Rückgabewert (0 bei Fehler) unsigned int duplicate = 0; // Rückgabewert (0 bei Fehler)
// 1. Array-Kopie auf dem Heap erstellen (muss mit free freigegeben werden!) if (len < 3) return 0; // Spielanforderung
// Array-Kopie auf dem Heap erstellen, da qsort in-place sortiert.
unsigned int sizeInBytes = len * sizeof(unsigned int); unsigned int sizeInBytes = len * sizeof(unsigned int);
unsigned int *tempArray = (unsigned int *)malloc(sizeInBytes); unsigned int *tempArray = (unsigned int *)malloc(sizeInBytes);
if (tempArray == NULL) { if (tempArray == NULL) {
return 0; // Speicherfehler return 0; // Speicherfehler
} }
@ -125,14 +128,15 @@ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
// Daten kopieren // Daten kopieren
memcpy(tempArray, numbers, sizeInBytes); memcpy(tempArray, numbers, sizeInBytes);
// 2. Sortieren der Kopie mit qsort (siehe Skript 14_effiziente_sortieralgorithmen.pdf) // Sortieren der Kopie mit qsort (siehe Skript effiziente sortieralgorithmen)
// qsort hat eine durchschnittliche Komplexität von O(n log n) [cite: 261] // qsort hat eine durchschnittliche Komplexität von O(n log n)
qsort(tempArray, len, sizeof(unsigned int), compareNumbers); qsort(tempArray, len, sizeof(unsigned int), compareNumbers);
// 3. Duplikat finden durch Vergleich benachbarter Elemente // Duplikat finden durch Vergleich benachbarter Elemente
for (unsigned int i = 0; i < len - 1; i++) for (unsigned int i = 0; i < len - 1; i++)
{ {
// Vergleiche Element i mit Element i+1 // Vergleiche Element i mit Element i+1
// Da das Array sortiert ist, stehen Duplikate nebeneinander
if (tempArray[i] == tempArray[i + 1]) if (tempArray[i] == tempArray[i + 1])
{ {
duplicate = tempArray[i]; duplicate = tempArray[i];
@ -140,7 +144,7 @@ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
} }
} }
// 4. Speicher freigeben! // Speicher freigeben!
free(tempArray); free(tempArray);
return duplicate; return duplicate;

36
stack.c
View File

@ -10,15 +10,15 @@
// Pushes data as pointer onto the stack. // Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data) StackNode *push(StackNode *stack, void *data)
{ {
//Speicher reservieren // Speicher reservieren für neuen Knoten (muss auf dem Heap liegen!)
StackNode *newNode = malloc(sizeof(StackNode)); StackNode *newNode = malloc(sizeof(StackNode));
if (!newNode) if (!newNode)
return stack; return stack; // Fehlerfall: Speicher konnte nicht allokiert werden
newNode->data = data; newNode->data = data; // Datenpointer übernehmen
newNode->next = stack; newNode->next = stack; // Der bisherige Stack ist jetzt der Nächste (LIFO)
return newNode; return newNode; // Der neue Knoten ist jetzt die Spitze des Stacks
} }
@ -26,38 +26,36 @@ StackNode *push(StackNode *stack, void *data)
// freed by caller.) // freed by caller.)
StackNode *pop(StackNode *stack) StackNode *pop(StackNode *stack)
{ {
// überprüfen ob stack einen wert besitzt // Check, ob der Stack leer ist
if (!stack) if (!stack)
return NULL; return NULL;
//oberstes element raussuchen und dieses auf free setzen
//den pointer dazu auf NULL setzen
StackNode *next = stack->next; StackNode *next = stack->next; // Speichere den Pointer auf das nächste Element
free(stack); free(stack); // Gib den Speicher des obersten Knotens frei
return next;
//stack returnen return next; // Gebe das neue oberste Element zurück
} }
// Returns the data of the top element. // Returns the data of the top element.
void *top(StackNode *stack) void *top(StackNode *stack)
{ {
//funktions return ist oberstes stack element // Check, ob der Stack leer ist
if (!stack) if (!stack)
return NULL; return NULL;
StackNode *next = stack->data; // Gebe nur die Daten zurück, ohne den Stack zu verändern
return next; return stack->data;
} }
// Clears stack and releases all memory. // Clears stack and releases all memory.
void clearStack(StackNode *stack) void clearStack(StackNode *stack)
{ {
// Iteriere solange, bis der Stack leer ist
while(stack != NULL) while(stack != NULL)
{ {
StackNode *next = stack->next; StackNode *next = stack->next; // Speichere den Nachfolger
free(stack); free(stack); // Gib den aktuellen Knoten frei
stack = next; stack = next; // Gehe zum nächsten Knoten
} }
} }