如何改组std :: vector?

时间:2011-08-03 12:27:59

标签: c++ shuffle stdvector

我正在寻找一种通用的,可重用的方法来在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);
}

6 个答案:

答案 0 :(得分:167)

从C ++ 11开始,你应该更喜欢:

#include <algorithm>
#include <random>

auto rng = std::default_random_engine {};
std::shuffle(std::begin(cards_), std::end(cards_), rng);

Live example on Coliru

如果您打算每次都生成不同的排列,请务必在多次调用rng时重复使用std::shuffle的同一个实例!


对于C ++ 98,您可以使用:

#include <algorithm>

std::random_shuffle(cards_.begin(), cards_.end());

答案 1 :(得分:9)

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;
}

答案 2 :(得分:5)

除了@Cicada所说的,你应该先播种,

srand(unsigned(time(NULL)));
std::random_shuffle(cards_.begin(), cards_.end());

Per @ FredLarson的评论:

  

此版本的random_shuffle()的随机源是   实现已定义,因此可能根本不使用rand()。然后srand()   没有效果。

所以YMMV。

答案 3 :(得分:2)

它甚至可以更简单,可以完全避免播种:

#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);

答案 4 :(得分:1)

如果您使用boost,则可以使用此类(debug_mode设置为false,如果您希望随机化可以在执行之间进行预测,则必须将其设置为{ {1}}):

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_));
    }
};

答案 5 :(得分:0)

根据您必须遵循的标准(C ++ 11 / C ++ 14 / C ++ 17),此“ cppreference”页面提供了很好的示例:https://en.cppreference.com/w/cpp/algorithm/random_shuffle