STL洗牌程序

STL中的洗牌程序为random_shuffle,其源码如下:
template <class RandomAccessIterator>                                             
inline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last) { 
    if(first != last)                                                             
        for(RandomAccessIterator i = first + 1; i != last; ++i)                   
            iter_swap(i, first + (rand() % ((i - first) + 1)));                   
} 

洗牌算法重要的是要保证算法符合均匀分布,即每张牌在每个位置出现的位置均等。
问题:random_shuffle算法洗出来的牌能符合均匀分布吗?
ANS:当然可以。证明如下:
假设有N张牌(假设点数为1~54,位置为1~54),采用倒推法,按算法可知,最后一个位置的牌(54)出现在其它位置上的概率均为1/54,符合原则
倒数第二个位置的牌(53),出现在其它位置的概率为1/53 - 1/53 * 1/54 = 1/54,也符合原则
扩展到任意位置的牌(n),其出现在其它位置的概率为1/n - 1/n * 1/(n+1) - 1/(n+1) * 1/(n+2) - ... - 1/53 * 1/54 = 1/54 (利用1/n - 1/n*1/(n+1) = 1/(n+1)),也符合原则
故该算法符合均匀分布原则。

C++11后STL弃用了random_shuffle,改为了随机数性能更好的函数shuffle,其中使用了正态分布来产生更接近随机的随机数,实现如下:

 void shuffle (RandomAccessIterator first, RandomAccessIterator last, URNG&& g)
{
  for (auto i=(last-first)-1; i>0; --i) {
    std::uniform_int_distribution<decltype(i)> d(0,i);
    swap (first[i], first[d(g)]);
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值