Re: Shuffling a linked list
- From: rem642b@xxxxxxxxx (Robert Maas, see http://tinyurl.com/uh3t)
- Date: Fri, 29 Dec 2006 13:28:57 -0800
From: "A. Farber" <Alexander.Far...@xxxxxxxxx>
I have a doubly-linked list of 32 playing cards, which I'd like
to randomly and evenly (!) shuffle.
Why only 32 instead of the usual 52? (Just curious.)
I have a list head with 2 pointers - to the very 1st and to the
last elements and I have 2 macros to insert an element at the
"head" or at the "tail".
Without some additional API, such as a tool for removing an element
from somewhere, the task cannot be accomplished. Initially you have
32 cards in the list, and if you use either insert tool even once
you now have 33 cards in the list, and there's no way to ever get
back to 32.
I'm thinking of having an integer variable i which I'd increase
by one while going through my list. And if rand(i) < 1 then I'd
move that element at the "head" of the list. Which should give each
card a 1/32 possibility to land at the "head" position.
That requires ability to delete an element from one place (i) and
insert it somewhere else (head).
Nope. Try simulating that manually with just four cards (compute
probability of each possible outcome, then group the results per
who's at the head of the class, add within each group to get
subtotals, and compare them) and watch how the results aren't as
you had hoped. For example, the very last element you start with
has 1/n chance of ending at head (good) but (n-1)/n chance of
ending at bottom and no chance whatsoever of ending anywhere else.
Try this instead: Start with k0=0 k1=n. Generate rand(k1) and move
*that* element to the top of the list. Now increase k0 and decrease
k1, and compute the rand(k1) again, but skip the first k0 elements
and select randomly only from the remaining elements, i.e. move
element# k0 + rand(k1) to top. Each time you select from fewer
elements from the end of what you've already chosen (now topmost
segment) to the very end. When you're down to just one remaining
element not yet selected (k0=n-1 k1=1), you're done already.
Note that you can speed it up slightly by having two such linked
lists, one with the original data or a copy of it, out of which you
are removing random elements, and a second initially empty where
you are inserting the selected elements.
This takes on the order of n**2 steps (n times through main loop,
but in each loop nearly n steps down the list to find the element
to move, or nearly n/2 when using the two-list version), but for n
only 32 this should be fast enough if you do it only at the start
of each game. If n were really large, or you wanted to shuffle many
times per second, then I'd suggest a n*log(n) algorithm instead, or
better just use a damn array, which you need allocate only once.
.
- Follow-Ups:
- Re: Shuffling a linked list
- From: A. Farber
- Re: Shuffling a linked list
- References:
- Shuffling a linked list
- From: A. Farber
- Shuffling a linked list
- Prev by Date: Re: Shuffling a linked list
- Next by Date: Re: Shuffling a linked list
- Previous by thread: Re: Shuffling a linked list
- Next by thread: Re: Shuffling a linked list
- Index(es):
Relevant Pages
|
|