[vox-tech] shuffling arrays in C?
Micah Cowan
vox-tech@lists.lugod.org
Mon, 25 Nov 2002 12:04:50 -0800
On Monday, November 25, 2002, at 11:21 AM, Bill Kendrick wrote:
> That 'do...while' loop will get slower and slower and slower until its
> painful, once you're down to the last few elements. But, on fast
> machines
> with a small array, it ain't so bad. :^)
If it's possible for your scheme, I'd probably prefer a linked list -
they are easier to swap and to shuffle.
> Another way to do it is to literally shuffle things. The example
> below is more like taking cards out two at a time and swapping them.
> (Well, that's literally what's going on with the array :^) )
>
>
> int i;
> int index_1, index_2;
> YOUR_STRUCT * temp_for_swap;
>
>
> /* Shuffle for a while... */
>
> for (i = 0; i < SOME_SUITABLY_LARGE_NUMBER; i++)
> {
> index_1 = rand() % N;
> index_2 = rand() % N;
>
> temp_for_swap = your_array[index_1];
> your_array[index_1] = your_array[index_2];
> your_array[index_2] = temp_for_swap;
> }
>
>
> This is pretty simple. There's probably more elegant ways of doing
> the swap, too. Oh, and that doesn't test for if index_1 == index_2
> (e.g., it swaps with itself), but hey, that doesn't matter.
> It's probably minisculy faster for not doing that comparison every
> iteration.
Yeah, but no matter how long you run, there's no way to be sure that a
significant number of cards were left as-is (which of course is true of
regular card-shuffling, too). But we can do a little better than real
shuffling; the method below is similar to how selection sorts work:
int i;
int j;
YOUR_STRUCT *temp_for_swap;
#define ELEMS_IN_ARY(a) (sizeof (a) / sizeof *(a))
for (i = 0; i != ELEMS_IN_ARY(your_array); ++i)
{
const int selection_size = ELEMS_IN_ARY(your_array) - (i + 1);
int selected_card = (i + 1) /* don't include the already selected
cards, or the card to swap with */
+ (int)((selection_size*1.0*rand())/(RAND_MAX+1.0)) /* see
rand(3) */
temp_for_swap = your_array[i];
your_array[i] = your_array[j];
your_array[j] = temp_for_swap;
}
The above is, of course, untested code...
-Micah