C++ STL shuffle 使用说明
说明
使用一个随机数产生器来打乱[first, last)之间元素的顺序。
有3个参数,前2个参数指定容器的范围,第3个参数指定随机数产生器。
函数签名如下:
template <class RandomAccessIterator, class URNG>
void shuffle (RandomAccessIterator first, RandomAccessIterator last, URNG&& g);
shuffle的大致原理
The function swaps the value of each element with some other randomly picked element
通过交换元素来实现的,顺次交换当前元素和一个随机选择的元素。
头文件
#include <algorithm>
例子:随机打乱一个数组
#include <iostream>
#include <random>
#include <algorithm>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << "before shuffle:\t";
for (int n : v) {
std::cout << n << " ";
}
std::cout << std::endl;
std::random_device rd;
std::mt19937 rng(rd());
std::shuffle(v.begin(), v.end(), rng);
std::cout << "after shuffle: \t";
for (int n : v) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
一种可能结果如下:
before shuffle: 1 2 3 4 5 6 7 8 9
after shuffle: 6 5 7 4 1 8 3 9 2
下面的代码是用来生成一个随机数产生器的
std::random_device rd;
std::mt19937 rng(rd());
随机数发生器使用有很多种,也可以使用如下的形式
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle(v.begin(), v.end(), std::default_random_engine(seed));
random_shuffle 和 shuffle的区别
推荐使用std::shuffle
。
std::shuffle
是从C++11之后才开始出现,必须与随机数生成器一起使用。
std::random_shuffle
在C++11之前就已经存在,可以不指定随机数生成器而使用默认的随机数生成器。
需要注意的是,std::random_shuffle
在 C++14
中弃用, C++17
中移除。所以推荐使用std::shuffle
。
std::random_shuffle
被废除的原因是std::random_shuffle
的随机数产生器使用了std::rand()
。
而std::rand()
使用了一个全局静态变量保存其状态,这样使得std::rand()
无法同时产生两个独立互不干扰的随机数流。
所以std::random_shuffle
由于使用了std::rand()
,产生的随机数质量不如std::shuffle
使用的均匀分布的随机数产生器URNG(Uniform Random Number Generator)产生的随机数
参考
https://zh.cppreference.com/w/cpp/algorithm/random_shuffle
http://www.cplusplus.com/reference/algorithm/shuffle/
https://meetingcpp.com/blog/items/stdrandom_shuffle-is-deprecated.html
https://www.geeksforgeeks.org/shuffle-vs-random_shuffle-c/