参考原文链接:
     
      https://blog.csdn.net/qq_25026989/article/details/89512769
     
    
   
    
     问题描述:
    
    
     洗牌算法是将原来的数组进行打散,使原数组的某个数在打散后的数组中的每个位置上等概率的出现。
    
   
    
     主要有3中经典的洗牌算法:
    
   
    
     1.
     
      抽牌
     
     :
    
   
1.初始化原始数组和新数组,原始数组长度为n(已知);
2.从还没处理的数组(假如还剩k个)中,随机产生一个[0, k)之间的数字p(假设数组从0开始);
3.从剩下的k个数中把第p个数取出;
4.重复步骤2和3直到数字全部取完;
5.从步骤3取出的数字序列便是一个打乱了的数列。
    
     时间复杂度为O(n*n),空间复杂度为O(n).
    
   
    
     2.
     
      换牌
     
     (
    
    
     原地打乱顺序
    
    
     ):
    
   
    1. 建立一个数组大小为 n 的数组 arr,分别存放 1 到 n 的数值;
    
    2. 生成一个从 0 到 n – 1 的随机数 x;
    
    3. 输出 arr 下标为 x 的数值,即为第一个随机数;
    
    4. 将 arr 的尾元素和下标为 x 的元素互换;
    
    5. 同2,生成一个从 0 到 n – 2 的随机数 x;
    
    6. 输出 arr 下标为 x 的数值,为第二个随机数;
    
    7. 将 arr 的倒数第二个元素和下标为 x 的元素互换;
    
    ……
    
    如上,直到输出 m 个数为止
   
    
    
    
     时间复杂度为O(n),空间复杂度为O(1)
    
   
    
     缺点必须知道数组长度n.原始数组被修改了,这是一个原地打乱顺序的算法,算法时间复杂度也从Fisher算法的 O(n2)提              升到了O(n)。由于是从后往前扫描,无法处理不知道长度或动态增长的数组。
    
   
    
     3.
     
      插牌
     
     (蓄水池抽样):
    
   
1.先选中第1到k个元素,作为被选中的元素。然后依次对第k+1至第N个元素做如下操作:
2.每个元素都有k/x的概率被选中,然后等概率的(1/k)替换掉被选中的元素。其中x是元素的序号。
    从N个元素中随机等概率取出k个元素(洗牌发牌可以认为k=1),N长度未知。
    
     在o(n)时间内对n个数据进行等概率随机            抽取
    
    。如果数据集合的量特别大或者还在增长(相当于未知数据集合总量),该算法依然可以等概率抽样.
   
 
