C++中std::shuffle 的使用

std::shuffle 的使用

std::shuffle 是 C++ 标准库中的一个函数,用于对容器中的元素进行随机排列(洗牌)。它的实现基于现代随机数生成器,因此比 std::random_shuffle 更安全和灵活(std::random_shuffle 在 C++14 被弃用,C++17 后被移除)。


1. 语法

#include <algorithm>
#include <random>

std::shuffle(RandomIt first, RandomIt last, URBG&& g);
  • firstlast:表示要随机打乱的范围([first, last))。
  • g:随机数生成器,必须符合 UniformRandomBitGenerator(如 std::mt19937)。
  • 返回值:无(函数会直接修改输入范围的内容)。

2. 使用示例

#include <iostream>
#include <vector>
#include <algorithm>
#include <random>  // 需要包含 <random> 头文件

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    // 创建随机数生成器
    std::random_device rd;  // 随机设备(硬件熵源)
    std::mt19937 g(rd());   // 梅森旋转算法(常用的随机数引擎)

    // 打乱顺序
    std::shuffle(vec.begin(), vec.end(), g);

    // 输出打乱后的结果
    std::cout << "Shuffled vector: ";
    for (int num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

3. 代码解析

  1. 创建随机数生成器

    • std::random_device rd;:用于生成种子。
    • std::mt19937 g(rd());:使用梅森旋转算法(Mersenne Twister)作为伪随机数引擎。
  2. 调用 std::shuffle 进行洗牌

    • std::shuffle(vec.begin(), vec.end(), g); 重新打乱 vec 中的元素顺序。
  3. 打印打乱后的数组

    • 遍历并输出 vec

4. 示例输出

Shuffled vector: 3 7 5 9 1 4 2 8 6

(输出的顺序是随机的,每次运行结果可能不同。)


5. 重要说明

  1. 为什么不用 std::random_shuffle

    • std::random_shuffle 需要内部调用 rand(),它的随机性较弱,而且 rand() 不是线程安全的。
    • std::shuffle 允许使用高质量的随机数生成器(如 std::mt19937)。
  2. std::mt19937 vs std::default_random_engine

    • std::default_random_engine 可能因不同的编译器实现不同,因此推荐使用 std::mt19937
  3. 如何使用固定种子进行可复现的随机洗牌?

    std::mt19937 g(42);  // 42 作为固定的随机种子
    std::shuffle(vec.begin(), vec.end(), g);
    

    这样每次运行代码都会得到相同的打乱结果。


6. 适用场景

  • 随机排序数据
  • 生成随机测试用例
  • 洗牌(如扑克牌游戏)
  • 打乱数据以避免排序偏差(如机器学习数据预处理)

7. 结论

std::shuffle 是现代 C++ 中推荐的随机洗牌方法,结合 std::mt19937 可以提供高质量的随机性,适用于各种随机排列的场景。

🚀 推荐使用 std::shuffle 代替 std::random_shuffle,并搭配 std::mt19937 以获得更好的随机性和可控性!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云SLAM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值