generated from freudenreichan/info2Praktikum-DobleSpiel
comments
This commit is contained in:
parent
cd4f74f9a5
commit
bb8bd2ace8
32
numbers.c
32
numbers.c
@ -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
36
stack.c
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user