如何洗牌 std::vector
How to shuffle a std::vector?
我正在寻找一种通用的、可重用的方式来在C++中洗牌std::vector
。这就是我目前的做法,但我认为它不是很有效,因为它需要一个中间数组并且它需要知道项目类型(在本例中为 DeckCard(:
srand(time(NULL));
cards_.clear();
while (temp.size() > 0) {
int idx = rand() % temp.size();
DeckCard* card = temp[idx];
cards_.push_back(card);
temp.erase(temp.begin() + idx);
}
从 C++11 开始,您应该首选:
#include <algorithm>
#include <random>
auto rng = std::default_random_engine {};
std::shuffle(std::begin(cards_), std::end(cards_), rng);
科里鲁的现场例子
如果您打算每次都生成不同的排列,请确保在多次调用中重复使用相同的rng
实例,以std::shuffle
!
此外,如果您希望程序在每次运行时创建不同的随机序列,则可以使用std::random_device
的输出为随机引擎的构造函数播种:
auto rd = std::random_device {};
auto rng = std::default_random_engine { rd() };
std::shuffle(std::begin(cards_), std::end(cards_), rng);
对于 C++98,您可以使用:
#include <algorithm>
std::random_shuffle(cards_.begin(), cards_.end());
http://www.cplusplus.com/reference/algorithm/shuffle/
// shuffle algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::shuffle
#include <vector> // std::vector
#include <random> // std::default_random_engine
#include <chrono> // std::chrono::system_clock
int main ()
{
// obtain a time-based seed:
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine e(seed);
while(true)
{
std::vector<int> foo{1,2,3,4,5};
std::shuffle(foo.begin(), foo.end(), e);
std::cout << "shuffled elements:";
for (int& x: foo) std::cout << ' ' << x;
std::cout << 'n';
}
return 0;
}
除了@Cicada所说的之外,您可能还应该先播种,
srand(unsigned(time(NULL)));
std::random_shuffle(cards_.begin(), cards_.end());
根据@FredLarson的评论:
此版本的 random_shuffle(( 的随机性来源是 实现定义,因此它可能根本不使用 rand((。然后 srand(( 不会有任何效果。
所以YMMV。
它可以更简单,可以完全避免种子设定:
#include <algorithm>
#include <random>
// Given some container `container`...
std::shuffle(container.begin(), container.end(), std::random_device());
每次程序运行时,这将产生一个新的随机播放。由于代码的简单性,我也喜欢这种方法。
这是有效的,因为我们所需要的std::shuffle
是一个 UniformRandomBitGenerator
,其要求std::random_device
满足。
注意:如果反复洗牌,最好将random_device
存储在局部变量中:
std::random_device rd;
std::shuffle(container.begin(), container.end(), rd);
如果你正在使用boost,你可以使用这个类(debug_mode
设置为false
,如果你想随机化可以预测的beetween执行,你必须将其设置为true
(:
#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include <algorithm> // std::random_shuffle
using namespace std;
using namespace boost;
class Randomizer {
private:
static const bool debug_mode = false;
random::mt19937 rng_;
// The private constructor so that the user can not directly instantiate
Randomizer() {
if(debug_mode==true){
this->rng_ = random::mt19937();
}else{
this->rng_ = random::mt19937(current_time_nanoseconds());
}
};
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
Randomizer(Randomizer const&); // Don't Implement
void operator=(Randomizer const&); // Don't implement
public:
static Randomizer& get_instance(){
// The only instance of the class is created at the first call get_instance ()
// and will be destroyed only when the program exits
static Randomizer instance;
return instance;
}
template<typename RandomAccessIterator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last){
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > random_number_shuffler(rng_, boost::uniform_int<>());
std::random_shuffle(first, last, random_number_shuffler);
}
int rand(unsigned int floor, unsigned int ceil){
random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
return (rand_(rng_));
}
};
您可以使用以下代码对其进行测试:
#include "Randomizer.h"
#include <iostream>
using namespace std;
int main (int argc, char* argv[]) {
vector<int> v;
v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);
v.push_back(6);v.push_back(7);v.push_back(8);v.push_back(9);v.push_back(10);
Randomizer::get_instance().random_shuffle(v.begin(), v.end());
for(unsigned int i=0; i<v.size(); i++){
cout << v[i] << ", ";
}
return 0;
}
根据您必须遵循的标准(C++11/C++14/C++17(,此"CPP首选项"页面提供了很好的示例: https://en.cppreference.com/w/cpp/algorithm/random_shuffle。
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- 连接和压缩标准::vector<std::字符串的最佳方法>
- C++从 std::vector<std::function<中删除 std::function>>
- 如何在构造函数初始值设定项列表中使用 n 个元素初始化 std::vector<std::time_t>
- 如何使用 CUDA 将 std::vector<std::string> 复制到 GPU 设备
- 编译错误 std::vector<std::shared_ptr<T>>迭代器和擦除方法
- 将 std::vector<std::unique_ptr<T>> 移动到 std::vector<std::shared_ptr<T>>
- 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?
- 使用 std::vector<std::future<int>> 和 std::async 启动几个线程时中止
- 为什么转置这个 std::vector<std::vector<std::string> > 这么慢?
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 在 boost::<double>asio::buffer 中使用像 std::vector<std::complex> 这样的参数
- 如何从 std::initializer_list<char const* 构建 std::vector<std::string>>
- 如何检查 std::vector<std::string> 的元素是否以某个子字符串开头?
- 在 std::vector<std::vector 中重新存储内部向量<TYPE>>
- 将 std::vector<std::string> 转换为 const char* const*
- 不能将结构push_back() 转换为 std::vector<std::shared_ptr<theStruct>> theVector
- SWIG:传递一个 std::vector< std::vector <double> >指向 python 的指针
- 将 std::vector<std::p air<const K, V>*> 转换为 std::vector<std::p air<const K, V>&g