在C++里生成不重复随机数的核心思路是:先把候选数字按顺序放进一个数组,然后利用标准库的shuffle算法配合随机设备把数组顺序彻底打乱,最后按顺序取用即可。这样每个数只出现一次,不存在重复问题。

为什么直接用rand容易重复
如果每次调用rand得到一个随机数,再判断是否已在结果集中,当范围较大而需要的数量也多时,冲突概率会上升,并且要去重就会写循环判断,代码又慢又啰嗦。更合理的做法是“全量填充加打乱”。
shuffle算法的工作逻辑
shuffle接收两个迭代器表示区间,以及一个随机数引擎。它使用给定引擎产生随机位置,对区间内元素做均匀交换,最终使原序列等概率变为任意一种排列。因为只是重排,所以元素集合不变、不会丢失也不会复制,正好满足不重复要求。
基础实现步骤
- 构造vector保存1到N的所有整数
- 用random_device和mt19937创建随机引擎
- 调用shuffle打乱vector
- 取前M个作为不重复随机数
完整代码示例
下面代码演示生成1到100之间10个不重复随机数:
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
int main() {
// 填充1到100
std::vector<int> nums;
for (int i = 1; i <= 100; ++i) {
nums.push_back(i);
}
// 创建随机引擎
std::random_device rd;
std::mt19937 g(rd());
// 打乱顺序
std::shuffle(nums.begin(), nums.end(), g);
// 取前10个,天然不重复
std::cout << "不重复随机数:";
for (int i = 0; i < 10; ++i) {
std::cout << " " << nums[i];
}
std::cout << std::endl;
return 0;
}
常见注意点
| 问题 | 说明 |
|---|---|
| 引擎复用 | 不要每次shuffle都新建random_device,可复用mt19937提升性能 |
| 线程安全 | 随机引擎不是线程安全的,多线程中要各自持有实例 |
| 旧版random_shuffle | 已被弃用,新代码应使用shuffle并显式传引擎 |
小结
用shuffle算法生成不重复随机数,本质是把“随机选数”转化为“随机排顺序”,逻辑清晰且效率稳定。掌握random_device与mt19937的配合,就能在各类C++项目中安全使用。