我有一个长度为1百万(0到1百万)的数据向量A.从A开始,我想创建包含A的索引的向量B(其长度仅为A的10%)。这些索引是从A中随机抽取的样本索引。我尝试使用srand()和random_shuffle,这是一个很好的为非常大的向量提取样本的方法?任何人都可以建议我。
std::vector <int> samplingIndex;
for (int i = 0; i < 1000000; ++i) { samplingIndex.push_back(i); }
std::srand(50);
std::random_shuffle(samplingIndex.begin(), samplingIndex.end());
在此之后,我从samplingIndex中取出前10%的索引来制作B。
答案 0 :(得分:1)
您可以使用Fisher–Yates shuffle,然后避免构建庞大的数组a
:
类似的东西:
// Fisher–Yates_shuffle
std::vector<int> FisherYatesShuffle(std::size_t size, std::size_t max_size, std::mt19937& gen)
{
assert(size < max_size);
std::vector<int> b(size);
for(std::size_t i = 0; i != max_size; ++i) {
std::uniform_int_distribution<> dis(0, i);
std::size_t j = dis(gen);
if(j < b.size()) {
if(i < j) {
b[i] = b[j];
}
b[j] = i;
}
}
return b;
}
答案 1 :(得分:0)
似乎合理。一个调整是你可以用这个替换你的for循环,以避免重复重新分配向量:
std::vector <int> samplingIndex(1000000);
std::iota(samplingIndex.begin(), samplingIndex.end(), 0);
如果您的收益百分比远小于10%,那么在[0,len(A))中生成随机数是值得的,直到您得到len(B)不同的值。
答案 2 :(得分:0)
您的代码是使用旧的C ++编写的。我认为你应该仔细研究新的C ++ 11/14中的随机性。
答案 3 :(得分:0)
如果您的输入来自AWGN源(或接近它),您可以每10个样本选择1个样本并在O(N)时间内完成工作(您希望10%的随机样本正确吗?)
否则,从巨大的矢量中提取10%的随机样本的一种非常有效的方法是每次选择的索引随机存储样本。继续挑选随机项目,如果已经采用了索引则重复。是的,是一种概率方法,但您在最佳和平均情况下实现了O(N)复杂性。最糟糕的情况是你一次又一次地选择相同的索引,但这意味着一个非常糟糕的PRNG实现:你可以假设最坏的情况是一个非常不可能的情况(只是保持在哈希函数中的几率足够低)您还可以使用链接列表和&#34;短路&#34;选定的样本(将PRNG输出空间减少到N-1)但这需要额外的内存来存储链表。