Random permutations

I am having trouble finding a decent way to randomly shuffle items in std::vectorand after some operations to restore the original order. I know this should be a pretty trivial algorithm, but I think I'm too tired ...

Since I have a limited user class of random number generators, I think I can’t use std::random_shufflethat in no way helps, because I also need to keep the original order. So, my approach was to create std::map, which serves as a comparison between the original and random positions, for example:

std::map<unsigned int, unsigned int> getRandomPermutation (const unsigned int &numberOfElements)
{
    std::map<unsigned int, unsigned int> permutation;

    //populate the map
    for (unsigned int i = 0; i < numberOfElements; i++)
    {
        permutation[i] = i;
    }

    //randomize it
    for (unsigned int i = 0; i < numberOfElements; i++)
    {
        //generate a random number in the interval [0, numberOfElements)
        unsigned long randomValue = GetRandomInteger(numberOfElements - 1U);

        //broken swap implementation
        //permutation[i] = randomValue;
        //permutation[randomValue] = i;

        //use this instead:
        std::swap(permutation[i], permutation[randomValue]);
    }

    return permutation;
}

I'm not sure if the above algorithm is the correct implementation for random permutation, so any improvements are welcome.

:

std::vector<BigInteger> doStuff (const std::vector<BigInteger> &input)
{
    /// Permute the values in a random order
    std::map<unsigned int, unsigned int> permutation = getRandomPermutation(static_cast<unsigned int>(input.size()));

    std::vector<BigInteger> temp;

    //permute values
    for (unsigned int i = 0; i < static_cast<unsigned int>(input.size()); ++i)
    {
        temp.push_back(input[permutation[i]]);
    }

    //do all sorts of stuff with temp

    /// Reverse the permutation
    std::vector<BigInteger> output;
    for (unsigned int i = 0; i < static_cast<unsigned int>(input.size()); ++i)
    {
        output.push_back(temp[permutation[i]]);
    }

    return output;
}

- , std::vector<BigInteger> , . , input, , , , ?

- , , ?:)

for (unsigned int i = 0; i < static_cast<unsigned int>(input.size()); ++i)
{
    BigInteger aux = input[i];
    input[i] = input[permutation[i]];
    input[permutation[i]] = aux;
}

EDIT: , "Fisher-Yates" shuffle, getRandomPermutation :

std::map<unsigned int, unsigned int> getRandomPermutation (const unsigned int &numberOfElements)
{
    std::map<unsigned int, unsigned int> permutation;

    //populate the map
    for (unsigned int i = 0; i < numberOfElements; i++)
    {
        permutation[i] = i;
    }

    //randomize it
    for (unsigned int i = numberOfElements - 1; i > 0; --i)
    {
        //generate a random number in the interval [0, numberOfElements)
        unsigned long randomValue = GetRandomInteger(i);

        std::swap(permutation[i], permutation[randomValue]);
    }

    return permutation;
}
+5
4

:

permutation[i] = randomValue;
permutation[randomValue] = i;

. , , . , .

- , , std::random_shuffle , . , , , "Fisher-Yates". , , N 0 .. N-1 , , N^N . N! N, N^N N!. , , , .. .

, ?

, , input , .

, "". , , , ( - , ). , permutation[i] == i i, i 1.

, .. . "" , , , . , i :

  • , i. , .
  • set current = i
  • swap index[current] index[permutation[current]]. , index[current] ( ), "" .
  • mark current "done"
  • permutuation[current] - i, . , , , . .
  • current = permutation[current] .

- / , / , , / .

, "" . inv perm , inv[perm[i]] == i i. , , , , .

, Fisher-Yates - Fisher-Yates, , vector<pair<size_t,size_t>>. . , . , .

+2

"" n , std::vector<size_t> index(n), index[x] = x 0 <= x < n, index. : original_vector[index[i]]. , .

... , , std::random_shuffle...

?

template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last,
                    RandomNumberGenerator& rand );

, , . http://www.sgi.com/tech/stl/RandomNumberGenerator.html

+4

, , , , - , .

, , clib, . , , , . .

. http://en.wikipedia.org/wiki/Linear_congruential_generator

0.. (n! -1) unrank . n , n , unrank - O (n). , O (n).

+1

For an ordered sequence of elements a,b,c,d,e, first create a new indexed sequence X=(0,a),(1,b),(2,c),(3,d),(4,e). Then you randomly shuffle this sequence and get the second element of each pair to get a random sequence. To restore the original sequence, you sort Xin stages, using the first element of each pair.

0
source

All Articles