贝利信息

c++中如何打乱数组顺序_c++ shuffle函数随机排列方法【汇总】

日期:2026-01-15 00:00 / 作者:裘德小鎮的故事
std::shuffle是C++11起推荐的打乱方式,需传入UniformRandomBitGenerator引擎(如std::mt19937),不可用std::rand或已移除的std::random_shuffle;支持vector、array和原生数组,但要注意迭代器范围与类型安全。

std::shuffle 是 C++11 起推荐的打乱方式

直接用 std::shuffle,别再手写 Fisher-Yates 或调 std::random_shuffle(C++17 已移除)。它要求传入一个符合 UniformRandomBitGenerator 要求的随机数引擎,比如 std::mt19937,不能只传 std::rand

常见错误是沿用旧教程写法:

std::random_shuffle(vec.begin(), vec.end()); // 错!C++17 删除,且线程不安全

打乱 std::array / 原生数组要小心迭代器类型

std::shuffle 接收前向迭代器,对 std::ar

ray 和 C 风格数组都可用,但写法稍有差异:

注意:传入的尾迭代器必须是 end,不是 end - 1,否则会漏掉最后一个元素或越界。

如果只能用 C++98 / 不支持 怎么办

没有 头、也不能用 std::shuffle 时,退回到手动实现 Fisher-Yates(Knuth shuffle),但必须用 std::rand() 配合 std::srand() 初始化——不过这有严重缺陷:

更稳妥的兼容方案是引入轻量 PRNG,例如 xorshift(几行代码),比依赖全局 rand 可控得多。

打乱 vector 或自定义类型要注意什么

std::shuffle 只要求元素可移动(或可复制),对 std::string、自定义 class 完全没问题——前提是它们满足 MoveConstructible 和 MoveAssignable。

真正容易被忽略的是:打乱前后,所有迭代器、引用、指针全部失效(对 std::vector 来说,这是 realloc 导致的)。如果打乱前保存了 &vec[3],打乱后它不一定还指向原值。