费希尔 - 耶茨洗牌

维基百科,自由的百科全书
 
 

所述费-耶茨洗牌是一种算法,用于产生随机排列的有限的序列 -in平原而言,算法打乱的序列。该算法有效地将所有元素放在帽子里; 它通过随机从帽子中绘制一个元素直到没有元素保留下来,从而不断确定下一个元素。该算法产生无偏置排列:每个排列的可能性相同。该算法的现代版本是有效的:它需要的时间与被洗牌的项目数和打乱他们的地方。

费雪耶茨洗牌得名罗纳德·费舍尔和弗兰克·耶茨,谁第一个描述它,并且也被称为克努特洗牌后,高德纳。被称为Sattolo算法的Fisher-Yates混洗的变体可用于生成长度为n的随机循环置换,而不是随机置换。

费希尔和耶茨的原始方法

Fisher-Yates shuffle以其原始形式在1938年由Ronald Fisher和Frank Yates在他们的生物,农业和医学研究统计表中描述他们对算法的描述使用铅笔和纸张; 随机数字表提供了随机性。用于生成数字1到N的随机置换的基本方法如下:

  1. 写下从1到N的数字。
  2. 在一个和剩余未使用数字(包含)之间选择一个随机数k
  3. 从低端算起,删除尚未删除的第k个数字,并将其写在单独列表的最后。
  4. 从第2步开始重复,直到所有数字都被删除。
  5. 在步骤3中记下的数字序列现在是原始数字的随机排列。

假设在上面的步骤2中选取的随机数是真正的随机和无偏的,那么所得到的置换也是如此。费舍尔和耶茨仔细描述了如何从所提供的表格中以任何希望的范围获得这样的随机数字,避免任何偏见。他们还建议使用一种更简单的方法 - 从一个到N选取随机数字并丢弃任何重复数据 - 以生成前半部分置换,并且仅将更复杂的算法应用于剩下的一半,在那里选择重复的数字否则会变得令人沮丧的常见。

现代算法

费雪耶茨洗牌的现代版,专为电脑使用,通过引进理查德Durstenfeld于1964年,并通过推广唐纳德·E·克努特在计算机程序设计艺术为“算法P(洗牌)”。Durstenfeld和Knuth在他的书的第一版中都没有承认费雪和耶茨的工作; 他们可能没有意识到这一点。随后的计算机编程艺术版提到了费雪和耶茨的贡献。[4]

Durstenfeld描述的算法不同于Fisher和Yates给出的算法,只是一个小而重要的方法。然而,费舍尔和耶茨方法的一个天真的计算机实现将花费不必要的时间来计算上述步骤3中的剩余数字,而Durstenfeld的解决方案是通过将每个“未击中”数字交换到列表末尾,迭代。与O2)相比,这样可以将算法的时间复杂度降低到On)。此更改提供以下算法(对于基于零的数组)。

-要随机阵列一个Ñ:元素(索引为0..n-1)
Ñ -1 DOWNTO 1
Ĵ ←随机整数,使得0≤ Ĵ
交换一个 [ Ĵ ]和一个 [ ]

将数组以相反方向(从最低索引到最高索引)进行混洗的等效版本是:

-要随机阵列一个Ñ元素(索引为0..n-1):
0 Ñ -2
Ĵ ←随机整数使得i&le; Ĵ < Ñ
交换一个 [ ]和一个 [j]的

示例

铅笔和纸张法

作为例子,我们将使用Fisher和Yates的原始方法将数字从1到8进行排列。我们将从一张草稿纸上写出数字开始:

范围 结果
    1 2 3 4 5 6 7 8  

现在我们从1到8 滚动一个随机数k - 让我们把它做成3 - 然后敲出便笺本上的第k个(即第3个)数字(当然是3),并将结果写下来:

范围 结果
1-8 3 1 2 3 4 5 6 7 8 3

现在我们选择第二个随机数,这次是从1到7:结果是4.现在我们删除第四个数字,这个数字尚未从便笺本中删除 - 这是数字5 - 并将其添加到结果中:

范围 结果
1-7 4 1 2 3 4 5 6 7 8 3 5

现在我们从1到6然后从1到5选择下一个随机数,依此类推,总是重复上面的删除过程:

范围 结果
1-6 1 2 3 4 5 6 7 8 3 5 7
1-5 3 1 2 3 4 5 6 7 8 3 5 7 4
1-4 4 1 2 3 4 5 6 7 8 3 5 7 4 8
1-3 1 1 2 3 4 5 6 7 8 3 5 7 4 8 1
1-2 2 1 2 3 4 5 6 7 8 3 5 7 4 8 1 6
    1 2 3 4 5 6 7 8 3 5 7 4 8 1 6 2

现代方法

我们现在使用Durstenfeld的算法来做同样的事情:这次,我们将它们替换为尚未选择的最后一个数字,而不是将所选数字删除并复制到别处。我们将从以前的1到8中写出数字开始:

范围 结果
    1 2 3 4 5 6 7 8  

对于我们的第一卷,我们从1到8滚动一个随机数:这次是6,所以我们将列表中的第6和第8个数字交换:

范围 结果
1-8 6 1 2 3 4 5 8 7 6

下一个随机数从1滚到7,结果是2.因此,我们交换第2和第7个数字并继续前进:

范围 结果
1-7 2 7 3 4 5 8 2 6

我们推出的下一个随机数是1到6,恰好是6,这意味着我们将第6个数字留在列表中(在上面的交换之后,现在是数字8),然后移动到下一个数字步。再次,我们以相同的方式进行,直到排列完成:

范围 结果
1-6 6 1 7 3 4 5 8 2 6
1-5 1 5 7 3 4 1 8 2 6
1-4 3 5 7 4 3 1 8 2 6
1-3 3 5 7 4 3 1 8 2 6
1-2 1 7 5 4 3 1 8 2 6

在这一点上,没有什么可以做的了,所以产生的排列是7 5 4 3 1 8 2 6。

Fisher–Yates shuffle 算法的更多相关文章

  1. Fisher–Yates shuffle 洗牌算法

    Fisher-Yates shuffle 是一种生成有限序列的随机排列的算法--简单地说,该算法可以对序列进行混排.本人能力有限,且懒.不会扒论文去研究该算法在数学上的证明,只能抄袭网上的博客总结一遍 ...

  2. 由乱序播放说开了去-数组的打乱算法Fisher–Yates Shuffle

    之前用HTML5的Audio API写了个音乐频谱效果,再之后又加了个播放列表就成了个简单的播放器,其中弄了个功能是'Shuffle'也就是一般播放器都有的列表打乱功能,或者理解为随机播放. 但我觉得 ...

  3. Fisher–Yates shuffle 洗牌算法(zz)

    1,缘起 最近工作上遇到一个问题,即将一组数据,比如[A,B,C,D,E]其中的两个B,E按随机排列,其他的仍在原来的位置: 原始数组:[A,B,C,D,E] 随机字母:[B,D] 可能结果:[A,B ...

  4. Fisher–Yates shuffle 洗牌(shuffle)算法

    今天在敲undersore的源码,数组里面有一个shuffle,把数组随机打乱. _.shuffle = function(obj) { var set = isArrayLike(obj) ? ob ...

  5. 【JavaScript】数组随机排序 之 Fisher–Yates 洗牌算法

    Fisher–Yates随机置乱算法也被称做高纳德置乱算法,通俗说就是生成一个有限集合的随机排列.Fisher-Yates随机置乱算法是无偏的,所以每个排列都是等可能的,当前使用的Fisher-Yat ...

  6. 洗牌算法shuffle

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

  7. 关于乱序(shuffle)与随机采样(sample)的一点探究

    最近一个月的时间,基本上都在加班加点的写业务,在写代码的时候,也遇到了一个有趣的问题,值得记录一下. 简单来说,需求是从一个字典(python dict)中随机选出K个满足条件的key.代码如下(py ...

  8. 常用的sort打乱数组方法真的有用?

    JavaScript 开发中有时会遇到要将一个数组随机排序(shuffle)的需求,一个常见的写法是这样: function shuffle(arr) { arr.sort(function () { ...

  9. 关于JavaScript的数组随机排序

    昨天了解了一下Fisher–Yates shuffle费雪耶兹随机置乱算法,现在再来看看下面这个曾经网上常见的一个写法: function shuffle(arr) { arr.sort(functi ...

随机推荐

  1. CF1139B Chocolates

    题目地址:CF1139B Chocolates 前一个必须要少于后一个,那么模拟+贪心即可 倒序模拟,每次在上次取的个数减一和这次可以取的最多数量之间取min 直到为0(注意不要减到负数) 再就是注意 ...

  2. log4j - 输出格式控制, PatternLayout参数含义以及详细配置

    转载自:https://blog.csdn.net/reserved_person/article/details/52849505 做项目被log4j的输出格式化参数搞烦了,索性把API的相关部分大 ...

  3. 原生js的开发笔记

    1.基本的dom操作 var a=document.getElementById('ma1').innerHTML;/获取html代码 alert(document.getElementById('m ...

  4. 3. Python 字典 常用办法总结

    Python字典客储存任意类型的对象,如字符串.数字.元祖.列表.字典.bool等. 优点:取值方便,速度快 1.创建字典 字典由键(key)和对应值(value)成对组成. 字典也被称作关联数组或哈 ...

  5. (转载)深度剖析 | 可微分学习的自适配归一化 (Switchable Normalization)

    深度剖析 | 可微分学习的自适配归一化 (Switchable Normalization) 作者:罗平.任家敏.彭章琳 编写:吴凌云.张瑞茂.邵文琪.王新江 转自:知乎.原论文参考arXiv:180 ...

  6. 6个Async/Await完胜Promise的原因

    友情提醒:NodeJS自从7.6版开始已经内置了对async/await的支持.如果你还没用过该特性,那么接下来我会给出一系列的原因解释为何你应该立即开始使用它并且会结合示例代码说明. async/a ...

  7. hybrid programming based on python and C/C++

    Python/C API Reference Manual¶ https://docs.python.org/3/c-api/index.html Extending and Embedding th ...

  8. android SDK与ADT版本更新问题

    android SDK与ADT版本更新问题 问题:This Android SDK requires Android Developer Toolkit version 14.0.0 or above ...

  9. Confluence 6 数据库表-集群(Clustering)

    下面的表格包含了 Confluence 站点使用集群的信息. clustersafety 在通常的情况下,这个表格只有一条记录. safetynumber 的值是 Confluence 被用来如何找到 ...

  10. Swift中使用oc代码桥接设置

    1 将oc的代码拖入项目中 2 新建一个头文件 在头文件中导入你想用的oc头文件  import "****.h" 3 在设置build Setting 中搜索bird 找到 Ob ...