1、算法思想
根据维基百科解释:TheFisher–Yates shuffle is analgorithm for generating a random permutation of a finite sequence—in plain terms, the algorithm shuffles the sequence. The algorithm effectively puts all the elements into a hat; it continually determines the next element by randomly drawing an element from the hat until no elements remain. The algorithm produces anunbiased permutation: every permutation is equally likely. The modern version of the algorithm is efficient: it takes time proportional to the number of items being shuffled and shuffles themin place.
Fisher–Yates shuffle是对有限序列生成一个随机排列的算法,所有的排列是等概率的,该算法是无偏的、高效的,算法的时间正比于乱序的数组。思想如下:
To shuffle an array a of n elements (indices 0…n-1):
for i from n-1 downto 0://数组i从n-1到0循环执行n次
random_choice j <-- random integer such that 0 ≤j ≤i;//生成一个0到n-1之间的随机索引
exchange a[j] and a[i] //将交换之后剩余的序列中最后一个元素与随机选取的元素交换
该算法就是python中random.shuffle函数的具体实现
import random
a = [1,2,3,4,5,6,7,8,9]
random.shuffle(a)
a
[9, 1, 3, 4, 6, 8, 7, 5, 2]
2、举例
各列含义:范围、当前数组随机交换的位置、剩余没有被选择的数、已经随机排列的数
第一轮:从1到8中随机选择一个数,得到6,则交换当前数组中第8和第6个数
第二论:从1到7中随机选择一个数,得到2,则交换当前数组中第7和第2个数
下一个随机数从1到6中摇出,刚好是6,这意味着只需把当前线性表中的第6个数留在原位置,接着进行下一步;以此类推,直到整个排列完成。
截至目前,所有需要的置乱已经完成,所以最终的结果是:7 5 4 3 1 8 2 6
3、python代码实现
给定产生随机数的函数random.int与数组arr,实现shuffle函数功能。
import numpy as np
import random
“”"
def Fisher_yate_shuffle(arr):
length=len(arr)
for i in range(length)[::-1]:#倒序遍历
j=random.randint(0,i) #随机选取0和i之间的一个数j
#exchange arr[i] and arr[j]
temp=arr[i]
arr[i]=arr[j]
arr[j]=temp
return arr
if name==‘main’:
array = np.arange(1,10)
shuffle = Fisher_yate_shuffle(array)
print(shuffle)
“”"
def rand():
return random.randint(0,100000000)
#当序列的长度小于我们随机的数,如何映射到指定范围
def Fisher_yate_shuffle(arr):
length=len(arr)
a = range(length) # 给定数组的长度列表
a.reverse() # 倒序方式进行遍历
for i in a: # 从大到小取索引
#j=random.randint(0,i)
j = rand()
j = j % length #取余操作进行映射
#exchange arr[i] and arr[j]
temp=arr[i]
arr[i]=arr[j]
arr[j]=temp
return arr
if name==‘main’:
array=np.arange(1,200)
shuffle = Fisher_yate_shuffle(array)
print(len(set(shuffle)))
print(len(shuffle))
4、Pencil-and-paper method
该方法与fisher_yates类似,只不过要重新开辟一个新数组,相当于循环通过随机选取原数组的值放到新数组中。
代码实现如下:
def pencil_paper_shuffle(arr):
arr = list(arr)
new_arr = []
length = len(arr)
print(length)
while(length>0):
j = random.randint(0,length-1)
new_arr.append(arr[j])
arr.remove(arr[j])
#arr[j] = arr[length-1]
length -=1
print(‘arr is {}—new_arr is {}’.format(arr, new_arr))
return new_arr
if name==‘main’:
array=np.arange(1,10)
shuffle = pencil_paper_shuffle(array)
print(shuffle)
————————————————
版权声明:本文为CSDN博主「spirits_of_snail」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qikaihuting/article/details/78224690