Shuffle array in C

前端 未结 7 1889
执念已碎
执念已碎 2020-11-22 03:15

I\'m looking for a function in ANSI C that would randomize an array just like PHP\'s shuffle() does. Is there such a function or do I have to write it on my own

7条回答
  •  执念已碎
    2020-11-22 03:46

    I’ll just echo Neil Butterworth’s answer, and point out some trouble with your first idea:

    You suggested,

    Iterate through the array for, say, 100 times and exchange a random index with another random index

    Make this rigorous. I'll assume the existence of randn(int n), a wrapper around some RNG, producing numbers evenly distributed in [0, n-1], and swap(int a[], size_t i, size_t j),

    swap(int a[], size_t i, size_t j) {
      int temp = a[i]; a[i] = a[j]; a[j] = temp;
    }
    

    which swaps a[i] and a[j]. Now let’s implement your suggestion:

    void silly_shuffle(size_t n, int a[n]) {
        for (size_t i = 0; i < n; i++)
            swap(a, randn(n), randn(n)); // swap two random elements
    }
    

    Notice that this is not any better than this simpler (but still wrong) version:

    void bad_shuffle(size_t n, int a[n]) {
        for (size_t i = 0; i < n; i++)
            swap(a, i, randn(n));
    }
    

    Well, what’s wrong? Consider how many permutations these functions give you: With n (or 2×n for silly_shuffle) random selections in [0, n-1], the code will “fairly” select one of n² (or 2×n²) ways to shuffle the deck. The trouble is that there are n! = n×(n-1)×⋯×2×1 possible arrangements of the array, and neither n² nor 2×n² is a multiple of n!, proving that some permutations are more likely than others.

    The Fisher-Yates shuffle is actually equivalent to your second suggestion, only with some optimizations that change (performance = 0, complexity = serious) to (performance = very good, complexity = pretty simple). (Actually, I’m not sure that a faster or simpler correct version exists.)

    void fisher_yates_shuffle(size_t n, int a[n]) {
        for (size_t i = 0; i < n; i++)
            swap(a, i, i+randn(n-1-i)); // swap element with random later element
    }
    

    ETA: See also this post on Coding Horror.

提交回复
热议问题