四种洗牌算法

(1).简单来说就是从原始数据中随机剔除一个数据,并将剔除的数据加入到新的列表中

官方点的话如下:

Fisher–Yates Shuffle 算法思想就是从原始数组中随机抽取一个新的数字到新数组中。

算法描述如下:

1. 从还没处理的数组(假如还剩k个)中,随机产生一个[0, k]之间的数字p(假设数组从0开 始);

2. 从剩下的k个数中把第p个数取出;

3. 重复步骤2和3直到数字全部取完;

4. 从步骤3取出的数字序列便是一个打乱了的数列。

 

比较好的代码写法如下:

#简单写法
import random
def shuffle(lis):
    #新列表
    result=[]
    while lis:
        p=random.randrange(0,len(lis))  #设置随机下标范围,左闭右开
        result.append(lis.pop(p))       #实现随机剔除数据,并将剔除的数据加入到新的列表中
    return result
lis=[1,2,2,3,3,4,5,10]
result=shuffle(lis)
print("洗完牌后的顺序为:",result)

一般的代码写法如下:

import random
def shuffle(lis):
    #新列表
    result=[]
    while lis:
        p=random.randrange(0,len(lis))  #设置随机下标范围,左闭右开
        value=lis[p]
        result.append(value)
        del lis[p]                         #lis.remove(lis[p]) ,remove在结果上没问题,但是在逻辑上有问题,因为如果有两个相同的2,想移除的是第一个2但是有可能会移除第二个2,不合逻辑。但是不影响结果。
    return result
lis=[1,2,2,3,3,4,5,10]
result=shuffle(lis)
print("洗完牌后的顺序为:",result)

缺点:创建新列表,浪费存储空间

扫描二维码关注公众号,回复: 5688786 查看本文章

(2)就像自己平时洗扑克牌一样,从上面排中随机抽出一张牌,然后放在最底下,然后从除了最后一张牌之外的牌中随机抽一张,放到最底下。再从除了最下面两张牌之外的牌中随机抽出一张,放在最底下,依次类推。

Knuth 和Durstenfeld 在Fisher 等人的基础上对算法进行了改进。每次从未处理的数据中随 机取出一个数字,然后把该数字放在数组的尾部,即数组尾部存放的是已经处理过的数字。这是一 个原地打乱顺序的算法,算法时间复杂度也从Fisher算法的O(n2)提升到了O(n)。

代码如下:

#原地打乱
import random
def shuffle(lis):
    for i in range(len(lis),0,-1):
        p=random.randrange(0,i)           #从0到i随机取值,0到i的范围逐渐缩小
        lis.append(lis.pop(p))            #把随机取出的值加在最后
    return lis
lis=[1,2,2,3,3,4,5,10]
result=shuffle(lis)
print("洗完牌后的顺序为",result)

缺点:在原始数据上打乱的,想看原始数据的话就看不到了。

(3)python下面自带的洗牌算法

其内部实现正是使用Knuth­Durstenfeld Shuffle算法。

import random
lis=[1,2,2,3,3,4,5,10]
random.shuffle(lis)
print(lis)

自带的洗牌算法见(4)

(4)Knuth­Durstenfeld Shuffle 是一个in­place算法,原始数据被直接打乱,有些应用中可能 需要保留原始数据,因此需要开辟一个新数组来存储打乱后的序列。Inside­Out Algorithm 算法的基本思想是设一游标i从前向后扫描原始数据的拷贝,在[0, i]之间随机一个下标j,然后用 位置j的元素替换掉位置i的数字,再用原始数据位置i的元素替换掉拷贝数据位置j的元素。其作用 相当于在拷贝数据中交换i与j位置处的值。

代码如下:

import random
def shuffle(lis):
    result=lis[:]
    for i in range(1,len(lis)):
        j=random.randrange(0,i)
        result[i],result[j]=result[j],result[i]
    return result
r=shuffle([1,2,2,3,3,4,5,10])
print(r)

猜你喜欢

转载自blog.csdn.net/qq_39112101/article/details/88769397