STL算法我实现之随机洗牌

简介: STL算法我实现之随机洗牌

将一个数组中的元素序列打算顺序进行重排,并需要保证重排后的每一种结果是等概率且随机的。下面的两种算法哪一种是正确的?(注:random(a,b)返回一个a~b的随机整数)

  1. for i=1 to n do swap( a[i], a[random(1,n)] );
  2. for i=1 to n do swap( a[i], a[random(i,n)] );

解释:

首先,1~n的序列打乱重排共有n!个不同的排列,且每种排列被选中的概率为1/N!,只有这样的算法才是等概率且随机的。

第一种算法将会产生n^n种情况,显然其中出现了重复的情况。那么会不会虽然出现重复,但每种排列重复的次数相同,所以算法依然是等概率且随机的呢?答案是,不会。

假设上述情况成立,则n^n必定n!整除。但是,绝大多数情况下,n!的质因子远多于n^n的质因子(即n的质因子)。根据Bertrand-Chebyshev定理,在n/2和n之间一定还有一个质数。这两个质数的乘积已经大于n了。搞了半天,第一种看似对称而美观的算法居然是错的!即对所有大于2的n,上述整除都不不可能的。

第二种算法是符合要求的随机洗牌算法。

使用数学归纳法证明:

1、当n=1时,所以元素arr[0]在任何一个位置的概率为1/1,命题成立。

2、假设当n=k时,命题成立,即原数组中任何一个元素在任何一个位置的概率为1/k。

3、则当n=k+1时,当算法执行完k次时,前k个元素在前k个位置的概率均为1/k。当执行最后一步时,前k个元素中任何一个元素被替换到第k+1位置的概率为:(1-1/(k+1)) * 1/k = 1/(k+1); 在前面k个位置任何一个位置的概率为(1-1/(k+1)) * 1/k = 1/(k+1);故前k个元素在任意位置的的概率都为1/(k+1)所以,对于前k个元素,它们在k+1的位置上概率为1/(k+1)。对于第k+1个元素,其在原位置的概率为1/k+1,在前k个位置任何一个位置的概率为:(1-k/(k+1))* (1/k)=1/(k+1),所以对于第k+1个元素,其在整个数组前k+1个位置上的概率也均为1/k+1。

综上所述,对于任意n,只要按照方案中的方法,即可满足每个元素在任何一个位置出现的概率均为1/n。

解释完了洗牌算法的原理,那下面就是自己实现的random_shuffle的代码。

void swap(int& a,int& b)//不要尝试用“抑或”运算完成元素的交换,详见抑或运算
{
   int temp=b;
   b=a;
   a=temp;
}
void randomShuffle(int array[], int len)
{
     for(int i=1;i<len;i++)
     {
         int j=rand()%(i+1);
         swap(array[i],array[j]);
     }
}

本文作者 : cyningsun

本文地址https://www.cyningsun.com/05-08-2012/stl-shuffle.html

版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!

# STL

  1. STL算法我实现之排列
  2. STL算法我实现之rotate
  3. SGI-STL源码剖析之IntroSort
  4. SGI-STL源码剖析之list::sort()
  5. SGI-STL源码剖析之Heap
目录
相关文章
|
4月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
90 0
|
8月前
|
算法 前端开发 Linux
【常用技巧】C++ STL容器操作:6种常用场景算法
STL在Linux C++中使用的非常普遍,掌握并合适的使用各种容器至关重要!
123 10
|
7月前
|
算法 C++
STL算法大全
以上只是一部分STL算法的简单概述,每一个算法都有其特定的使用场景和规则,具体使用时需要参考相关文档或者教程进行深入理解和学习。
48 0
|
9月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(5) 常用算术生成算法
黑马c++ STL常用算法 笔记(5) 常用算术生成算法
|
9月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(4) 常用拷贝和替换算法
黑马c++ STL常用算法 笔记(4) 常用拷贝和替换算法
|
9月前
|
存储 算法 搜索推荐
黑马c++ STL常用算法 笔记(3) 排序算法
黑马c++ STL常用算法 笔记(3) 排序算法
|
9月前
|
算法 C++
黑马c++ STL常用算法 笔记(2) 查找算法
黑马c++ STL常用算法 笔记(2) 查找算法
|
8月前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
|
9月前
|
算法 C++
c++算法学习笔记 (21) STL
c++算法学习笔记 (21) STL
|
9月前
|
算法 C++ 容器
黑马c++ STL常用算法 笔记(6) 常用集合算法
黑马c++ STL常用算法 笔记(6) 常用集合算法