Commit ca096daa authored by Dominik Widhalm's avatar Dominik Widhalm
Browse files

Replaced inefficient shuffling algorithm in task 6.06

parent b58defbc
......@@ -10,8 +10,8 @@
* Info: *
* -) The name of the directory can be entered as: *
* "songs", "./songs", "songs/" or "./songs/" *
* -) Shuffle an array, see: *
* http://www.geeksforgeeks.org/shuffle-a-given-array/ *
* -) Swap two nodes of a simple-linked list, see: *
* geeksforgeeks.org/swap-nodes-in-a-linked-list-without-swapping-data*
* -) Read MP3 IDE3v1 Tag, see: *
* www.vlsi.fi/fileadmin/software/VS10XX/mp3tag.c *
* *
......@@ -32,7 +32,7 @@
// Maximum number of songs to read in
#define SONGS_MAX 20
// (Optional) print the list before shuffling
#define DEBUG 1
#define DEBUG 0
/***** TYPEDEFS ***************************************************************/
......@@ -54,7 +54,7 @@ song_t *songs_new (char *file);
int songs_scan (song_t **head, const char *dir);
void songs_print (song_t *head);
void songs_shuffle (song_t **head);
void swap (song_t **a, song_t **b) ;
void songs_swap (song_t **head, int x, int y);
/***** LOCAL FUNCTIONS ********************************************************/
......@@ -302,68 +302,93 @@ void songs_print (song_t *head) {
* @param head Pointer to pointer to the first list element *
******************************************************************************/
void songs_shuffle (song_t **head) {
/* Array to store the entry's addresses */
song_t *addresses[SONGS_MAX] = {NULL};
/* Temporary variable for the number of entries */
int entries = 0;
/* Temporary pointer to traverse the list */
song_t *curr = *head;
/* Go through the list and store the addresses */
/* Count the number of songs in the list */
while (curr != NULL) {
/* Store the current address */
addresses[entries] = curr;
/* Increment number of entries */
entries++;
/* Go to next element */
curr = curr->next;
}
/* Shuffle using the Fisher–Yates shuffle algorithm */
for (int i=(entries-1); i>0; i--) {
/* Get a random index between 0 and i */
int j = rand()%(i+1);
/* Swap current element with the "random" element */
swap(&addresses[i],&addresses[j]);
}
/* Recreate list with randomly picked addresses */
/* Randomly replace to list elements "number of elements"-times */
for (int i=0; i<entries; i++) {
/* Check if it's currently the first element */
if (i==0) {
/* Set head to the new first element */
*head = addresses[i];
/* Set next initially to NULL */
(*head)->next = NULL;
/* Save head as new current element */
curr = *head;
/* For all other elements */
} else {
/* Set next pointer of current element to new element */
curr->next = (song_t*)addresses[i];
/* Set current to next element */
curr = curr->next;
/* Set next initially to NULL */
curr->next = NULL;
}
/* Get a random number between 0 and (entries-1) */
int cnt1 = rand()%entries, cnt2;
/* Get a second number which differs from the first one */
do {
cnt2 = rand()%entries;
} while (cnt2 == cnt1);
/* Swap the two elements */
songs_swap(head, cnt1, cnt2);
}
/* A void function has nothing to return */
return;
}
/******************************************************************************
* swap *
* @brief Function to swap to long integer values. *
* songs_swap *
* @brief Function to swap two nodes in the list given by their number. *
* *
* This function exchanges to long integer values and is used for *
* shuffling an array. *
* This function swaps two nodes in a given list specified by their *
* respective offset number from the beginning of the list. *
* *
* @param a Pointer to the first long int variable *
* @param b Pointer to the second long int variable *
* Taken from: *
* geeksforgeeks.org/swap-nodes-in-a-linked-list-without-swapping-data/ *
* *
* @param head Pointer to pointer to the first list element *
* @param x Number of the first element *
* @param y Number of the second element *
******************************************************************************/
void swap (song_t **a, song_t **b) {
/* Do a triangular exchange */
song_t *tmp = *a;
*a = *b;
*b = tmp;
void songs_swap (song_t **head, int x, int y) {
/** Preparation before swapping **/
/* Get address of the first element and store its neighbors */
song_t *prevX = NULL, *currX = *head;
for (int i=0; i < x; i++) {
prevX = currX;
currX = currX->next;
}
/* Get address of the second element and store its neighbors */
song_t *prevY = NULL, *currY = *head;
for (int i=0; i < y; i++) {
prevY = currY;
currY = currY->next;
}
/* Check if valid addresses have been acquired */
if ((currX == NULL) || (currY == NULL)) {
/* At least one address is invalid -- return */
return;
}
/** Actual swapping **/
/* Check if x is not the list head */
if (prevX != NULL) {
/* Switch previous element of x's pointer from x to y */
prevX->next = currY;
/* If x was the list head */
} else {
/* Make y the new head element */
*head = currY;
}
/* Check if y is not the list head */
if (prevY != NULL) {
/* Switch previous element of y's pointer from y to x */
prevY->next = currX;
/* If y was the list head */
} else {
/* Make x the new head element */
*head = currX;
}
/* Finally swap the next pointers of both elements */
song_t *temp = currY->next;
currY->next = currX->next;
currX->next = temp;
/* A void function has nothing to return */
return;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment