我无法找出随机洗牌在元素的体面的方式std::vector
和,一些操作后,恢复了原来的顺序。 我知道,这应该是一个相当琐碎的算法,但我想我太累了...
因为我不得不使用定制的随机数生成器类,我想我不能使用std::random_shuffle
,不反正帮助,因为我还需要保留原来的顺序。 所以,我的方法是创建一个std::map
充当了原来的位置和随机的,这样的映射:
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;
}
我不知道的是,以上的算法是随机排列正确的实现,所以任何改进都欢迎。
现在,这里是如何我已经成功地利用这个排列地图:
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;
}
编辑:继史蒂夫的有关使用“费舍尔-耶茨的”洗牌的话,我改变了我的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;
}