Shuffling an array

VernonDozier 1 Tallied Votes 801 Views Share

This snippet is similar to my snippets on how to create random numbers without repeats, particularly this one.

This snippet is different in that it takes an already existing array and "shuffles" it so that the order appears random. No checking is done to make sure that there are no duplicates in the array.

Try changing ARRAY_SIZE and NUM_SWAPS in the code and see how that affects the "randomness" of the array.

/* This is a shuffling program.  It takes an array of integers and "shuffles"
   it so the order is more or less "random" by swapping array indexes.  The more
   swaps you make, the more random the order will appear.

   This particular example simply takes an array of 10 integers containing the
   numbers 0 through 9 and shuffles it.  The concept is easily to expand on
   though and you can easily make this program work for doubles, floats, chars, etc.,
   or make a template from it.

   srand, rand, and time appear to be part of the iostream library, but I have
   included ctime and cstdlib because you need them for the srand, time, and rand
   functions if you are not including iostream.
*/

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;


int main ()
{
    srand (time (NULL));

    const int ARRAY_SIZE = 10;
    const int NUM_SWAPS = 1000;

    // create unshuffled array
    int array[ARRAY_SIZE];
    for (int i = 0; i < ARRAY_SIZE; i++)
        array[i] = i;

    int swapIndex1, swapIndex2, temp;

    for (int i = 0; i < NUM_SWAPS; i++)
    {
        swapIndex1 = rand () % ARRAY_SIZE;
        swapIndex2 = rand () % ARRAY_SIZE;

        if (swapIndex1 == swapIndex2)
            i--;  // indexes are the same.  Nothing to swap, so don't increment swap
                  // counter i.  for-loop increments i, so decrement here
        else
        {
            // swap the values
            temp = array[swapIndex1];
            array[swapIndex1] = array[swapIndex2];
            array[swapIndex2] = temp;
        }
     }

     // display
     for (int i = 0; i < ARRAY_SIZE; i++)
         cout << array[i] << endl;

     return 0;
}

Dani AI

Generated

Good point, — that swap-based snippet does what it says: it permutes the existing array so any duplicate values stay duplicates, and changing ARRAY_SIZE or the number of swaps will change how “mixed” the output looks. A quick experimental tip: increasing the swap count makes the result look more random, but it does not guarantee a uniform distribution of permutations and it is inefficient compared with purpose-built shuffles.

For a correct, unbiased shuffle use the Fisher–Yates (Knuth) shuffle or the C++ standard helper std::shuffle. Those produce each permutation with equal probability in O(n) time. Avoid rand() % n because it creates modulo bias when RAND_MAX+1 is not a multiple of n. For modern C++ prefer <random> and std::mt19937 seeded once (or std::random_device for non-reproducible runs).

Example (C++11+): use std::shuffle with a proper engine

#include <algorithm>
#include <random>

std::random_device rd;
std::mt19937 gen(rd());           // or use a fixed seed for reproducible tests
std::shuffle(array, array + ARRAY_SIZE, gen);

Or the explicit Fisher–Yates using uniform_int_distribution:

for (int i = ARRAY_SIZE - 1; i > 0; --i) {
    std::uniform_int_distribution<int> dist(0, i);
    std::swap(array[i], array[dist(gen)]);
}

Practical notes: seed once at program start (not inside a loop), use a fixed seed when you need reproducible behavior, and use a cryptographic RNG only when security is required (standard engines are not CSPRNGs). If you need a shuffled sequence of unique integers, generate the ordered range (e.g., with std::iota) then shuffle — that is simpler and guaranteed unique.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.