C++如何基于给定数组生成多个不重复的随机打乱数组?
问题原因分析
- 核心问题是指针共享错误:你最初的
generate_population函数只调用了一次new int[size]申请内存,后续所有std::random_shuffle操作都是修改同一块内存的内容,同时你把同一个指针ptr赋值给了population数组的所有元素,最终所有population[i]都指向同一块内存,自然输出内容完全一致,该问题和随机种子无关。 - 次要问题是
std::random_shuffle本身的缺陷:该函数从C14开始已经被官方弃用,C17正式移除,它的随机数来源实现未定义,部分实现不依赖std::rand,所以你设置std::srand也可能无法生效。另外std::time(0)返回的是秒级时间戳,如果你多次启动程序间隔小于1秒,确实会出现种子相同的问题,但你本次遇到的问题和该特性无关。
方案说明
你修改后的代码使用C11引入的std::shuffle搭配<random>库的随机引擎,是C标准推荐的数组打乱方案,完全适配你的场景,运行结果正确。
关于效率的相关说明:
std::shuffle的时间复杂度是O(n),生成size个随机排列的总时间复杂度为O(size²),这是该场景下的理论最低复杂度,你的实现效率已经达标。- 可优化点:你当前的代码每次打乱后会把结果复制回
ptr作为下一次打乱的基础,如果你需要的是独立的随机排列,可以删掉std::copy(another, another + size, ptr);这行,每次都复制最开始的初始有序数组即可,既可以避免不同排列之间的相关性,还能省一次拷贝操作。
更安全的实现示例
推荐使用std::vector代替裸指针,避免手动管理内存导致的泄漏问题,参考代码如下:
#include <vector> #include <algorithm> #include <random> #include <cstdio> int main() { constexpr int size = 5; // 初始有序数组 const std::vector<int> base = [](){ std::vector<int> tmp(size); for(int i=0; i<size; i++) tmp[i] = i; return tmp; }(); // 存储所有打乱后的数组 std::vector<std::vector<int>> population; population.reserve(size); std::random_device rd; std::default_random_engine dre(rd()); for(int i=0; i<size; i++) { std::vector<int> tmp = base; std::shuffle(tmp.begin(), tmp.end(), dre); population.push_back(std::move(tmp)); } // 输出结果 for(int i=0; i<size; i++) { printf("%d: ", i); for(int j=0; j<size; j++) { if(j>0) printf(", "); printf("%d", population[i][j]); } printf("\n"); } return 0; }
内容的提问来源于stack exchange,提问作者NotALolicon
相关产品推荐
相关产品推荐

