为什么渔民是最有用的改组算法?

时间:2010-03-17 00:59:52

标签: algorithm shuffle

你会说现代版本的渔民是最无偏见的改组算法吗? 您如何解释数组中的每个元素都有1 / n的概率在其原始位置?

2 个答案:

答案 0 :(得分:7)

给定一个完美的伪随机数生成器(Mersenne Twister非常接近),Fisher-Yates算法是完全无偏的,因为每个排列具有相同的发生概率。这很容易用感应证明。 Fisher-Yates算法可以如下递归写入(在Python语法伪代码中):

def fisherYatesShuffle(array):
    if len(array) < 2:
        return

    firstElementIndex = uniform(0, len(array))
    swap(array[0], array[firstElementIndex])
    fisherYatesShuffle(array[1:])

每个索引被选为firstElementIndex的概率相等。当你递归时,你现在有相同的概率选择任何仍然留下的元素。

编辑:算法已在数学上证明是无偏见的。由于该算法是非确定性的,因此在统计上测试实现是否正常工作的最佳方法。我会采用一些任意但小的大小的数组,将其多次洗牌(从每次输入的相同排列开始)并计算每个输出排列发生的次数。然后,我会使用Pearson's Chi-square Test测试此分布的均匀性。

答案 1 :(得分:3)

(现代,又称“Knuth”)Fisher–Yates洗牌是

  • 实施相对简单
  • 相当有效的O(n)时间和O(1)或实际上O(0)的空间
  • 无偏见(每个排列都是等概率的)
  • 众所周知/熟悉,经过验证,经过测试。

我们还能从算法中得到什么呢?嗯,是的,当排列数量变大时,人们可能会尝试别的东西,但大多数情况下并没有涉及如此巨大的数量?)

修改: '只是注意到这个答案回应了问题的标题,而不是内容。 (这就是为什么让问题的这两部分更好地匹配是好的...)
简而言之,shuffle 与用于实现算法的特定RNG 一样随机。
一个直观的解释是,对于具有m个元素的数组,即使作为n,循环的减小控制变量向下变为1,位置n处的单元格可能被交换的可能单元减少,这个单元格的概率减小很容易被移动增加的比例完全相同。换句话说,数组的最后一个元素可以在数组中的任何位置结束,但它只有一次机会被移动(在第一次迭代时)。要移动的倒数第二个元素的位置要少一个,但是在第一次迭代期间可能很容易移动的概率为1 / m。等