Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
master-embedded-systems
c-exercise-solutions public
Commits
ca096daa
Commit
ca096daa
authored
Dec 13, 2017
by
Dominik Widhalm
Browse files
Replaced inefficient shuffling algorithm in task 6.06
parent
b58defbc
Changes
1
Show whitespace changes
Inline
Side-by-side
ch_6/task_06/main.c
View file @
ca096daa
...
...
@@ -10,8 +10,8 @@
* Info: *
* -) The name of the directory can be entered as: *
* "songs", "./songs", "songs/" or "./songs/" *
* -) S
huffle an array, see:
*
*
http://www.
geeksforgeeks.org/s
huffle-a-given-array/
*
* -) S
wap two nodes of a simple-linked list, see:
*
* geeksforgeeks.org/s
wap-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
;
}
/******************************************************************************
* s
wap
*
* @brief Function to swap to
long integer values.
*
* s
ongs_swap
*
* @brief Function to swap t
w
o
nodes in the list given by their number.
*
* *
* This function
exchange
s to
long integer values and is used for
*
*
shuffling an array.
*
* This function
swap
s t
w
o
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
;
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment