python实现洗牌算法_洗牌算法shuffle

本文介绍了三种常见的洗牌算法:Fisher–Yates Shuffle、Knuth-Durstenfeld Shuffle 和 Inside-Out Algorithm,并提供了每种算法的 Python 实现代码。此外,文章还提到了 Python 的 random 模块中的 shuffle 方法及其内部实现。
摘要由CSDN通过智能技术生成

对这个问题的研究始于一次在群里看到朋友发的洗牌面试题。当时也不知道具体的解法如何,于是随口回了一句:每次从剩下的数字中随机一个。过后找相关资料了解了下,洗牌算法大致有3种,按发明时间先后顺序如下:

一、Fisher–Yates Shuffle

算法思想就是从原始数组中随机抽取一个新的数字到新数组中。算法英文描述如下:

Write down the numbers from 1 through N.

Pick a random number k between one and the number of unstruck numbers remaining (inclusive).

Counting from the low end, strike out the kth number not yet struck out, and write it down elsewhere.

Repeat from step 2 until all the numbers have been struck out.

The sequence of numbers written down in step 3 is now a random permutation of the original numbers.

python实现代码如下:

#Fisher–Yates Shuffle

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

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

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

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

importrandomdefshuffle(lis):

result=[]whilelis:

p=random.randrange(0, len(lis))

result.append(lis[p])

lis.pop(p)returnresult

r= shuffle([1, 2, 2, 3, 3, 4, 5, 10])print(r)

二、Knuth-Durstenfeld Shuffle

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

以下两种实现方式的差异仅仅在于遍历的方向而已。下面用python实现前一个:

#Knuth-Durstenfeld Shuffle

defshuffle(lis):for i in range(len(lis) - 1, 0, -1):

p= random.randrange(0, i + 1)

lis[i], lis[p]=lis[p], lis[i]returnlis

r= shuffle([1, 2, 2, 3, 3, 4, 5, 10])print(r)

三、Inside-Out Algorithm

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

python代码实现如下:

#Inside-Out Algorithm

defshuffle(lis):

result=lis[:]for i in range(1, len(lis)):

j=random.randrange(0, i)

result[i]=result[j]

result[j]=lis[i]returnresult

r= shuffle([1, 2, 2, 3, 3, 4, 5, 10])print(r)

四、后话

前面用python实现了三种洗牌算法,其实python random模块也有个shuffle方法,用法如下:

其内部实现正是使用Knuth-Durstenfeld Shuffle算法,不信您看代码:-):

参考:

http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值