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));
// 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;
// Allokiere Speicher für 'len' unsigned int
// Array auf dem Heap allokieren
unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int));
if (numbers == NULL)
@ -53,23 +53,23 @@ unsigned int *createNumbers(unsigned int len)
return NULL;
}
// 2. Binären Suchbaum initialisieren
// Binären Suchbaum initialisieren für Duplikatprüfung
TreeNode *treeRoot = NULL;
// Variablen für Schleife und Zufallszahl
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
for (unsigned int i = 0; i < len - 1; i++)
{
do
{
// 3a. Zufallszahl generieren [1, 2 * len]
// Zufallszahl generieren [1, 2 * len]
// Formel: (rand() % (Obergrenze - Untergrenze + 1)) + Untergrenze
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.
// isDuplicate wird auf 1 gesetzt, wenn die Zahl schon existiert.
treeRoot = addToTree(
@ -89,11 +89,11 @@ unsigned int *createNumbers(unsigned int len)
} while (isDuplicate); // Solange eine Duplikat-Nummer generiert wurde, wiederhole.
// 4. Eindeutige Zahl im Array speichern
// Eindeutige Zahl im Array speichern
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]
// 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
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.
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)
// 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 *tempArray = (unsigned int *)malloc(sizeInBytes);
if (tempArray == NULL) {
return 0; // Speicherfehler
}
@ -125,14 +128,15 @@ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
// Daten kopieren
memcpy(tempArray, numbers, sizeInBytes);
// 2. Sortieren der Kopie mit qsort (siehe Skript 14_effiziente_sortieralgorithmen.pdf)
// qsort hat eine durchschnittliche Komplexität von O(n log n) [cite: 261]
// Sortieren der Kopie mit qsort (siehe Skript effiziente sortieralgorithmen)
// qsort hat eine durchschnittliche Komplexität von O(n log n)
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++)
{
// Vergleiche Element i mit Element i+1
// Da das Array sortiert ist, stehen Duplikate nebeneinander
if (tempArray[i] == tempArray[i + 1])
{
duplicate = tempArray[i];
@ -140,7 +144,7 @@ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
}
}
// 4. Speicher freigeben!
// Speicher freigeben!
free(tempArray);
return duplicate;

36
stack.c
View File

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