Fisher–Yates shuffle 算法——对给定数组进行乱序

版权声明:未经本人许可,不得用于商业用途及传统媒体。转载请注明出处! https://blog.csdn.net/qikaihuting/article/details/78224690

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 ≤ji;//生成一个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=shuffle_arr(array)
    print(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)



猜你喜欢

转载自blog.csdn.net/qikaihuting/article/details/78224690