从包含n个元素的向量中随机选择m个元素

时间:2012-02-18 23:20:01

标签: c++ random vector

我有一个包含n元素的向量。我需要从矢量中随机选择m元素的子集而不重复。这样做最有效的方法是什么?我需要在我的代码中执行数千次这样的操作。

我最关心的解决方案是使用rand()k0之间生成一个随机数n。然后选择向量中的k元素并将其插入std::set。继续这样做,直到集合的大小等于m。我现在确信该集合包含从m元素集中随机选择的n个唯一元素。

其他可能的解决方案是什么?

感谢。

2 个答案:

答案 0 :(得分:37)

你想要一个Fisher-Yates shuffle(在M次迭代后停止):

template<class BidiIter >
BidiIter random_unique(BidiIter begin, BidiIter end, size_t num_random) {
    size_t left = std::distance(begin, end);
    while (num_random--) {
        BidiIter r = begin;
        std::advance(r, rand()%left);
        std::swap(*begin, *r);
        ++begin;
        --left;
    }
    return begin;
}

http://ideone.com/3A3cv的演示。当你只需要一些随机数时,这明显快于std::random_shuffle,即使N==M也应该是相同的速度。

答案 1 :(得分:3)

你可以这样做的一种方法是创建一个向量的所有索引的列表,将它们混洗,然后将第一个n作为所选对象的索引:

struct rangegenerator {
    rangegenerator(int init) : start(init) { }

    int operator()() {
        return start++;
    }

    int start;
};

vector<T> numbers; // this is filled somewhere else

vector<int> indices(numbers.size());

generate(begin(indices), end(indices), rangegenerator(0));

random_shuffle(begin(indices), end(indices));

// then take the first n elements of indices and use them as indices into numbers