费雪耶兹(Fisher–Yates) 也被称作高纳德( Knuth)随机置乱算法
来源:互联网 发布:破解软件网站 编辑:程序博客网 时间:2024/04/29 10:24
Fisher–Yates随机置乱算法也被称做高纳德置乱算法,通俗说就是生成一个有限集合的随机排列。Fisher-Yates随机置乱算法是无偏的,所以每个排列都是等可能的,当前使用的Fisher-Yates随机置乱算法是相当有效的,需要的时间正比于要随机置乱的数,不需要额为的存储空间开销。
一、算法流程:
需要随机置乱的n个元素的数组a:
for i 从n-1到1
j <—随机整数(0 =< j <= i)
交换a[i]和a[j]
end
二、实例
各列含义:范围、当前数组随机交换的位置、剩余没有被选择的数、已经随机排列的数
第一轮:从1到8中随机选择一个数,得到6,则交换当前数组中第8和第6个数
第二论:从1到7中随机选择一个数,得到2,则交换当前数组中第7和第2个数
下一个随机数从1到6中摇出,刚好是6,这意味着只需把当前线性表中的第6个数留在原位置,接着进行下一步;以此类推,直到整个排列完成。
截至目前,所有需要的置乱已经完成,所以最终的结果是:7 5 4 3 1 8 2 6
三、Java源代码
package simpleGa;import java.util.Arrays;import java.util.Random;public class Test {public static void main(String[] args) {int[] arr = new int[10];int i;//初始的有序数组System.out.println("初始有序数组:");for (i = 0; i < 10; i++) {arr[i] = i + 1;System.out.print(" " + arr[i]);}//费雪耶兹置乱算法System.out.println("\n" + "每次生成的随机交换位置:");for (i = arr.length - 1; i > 0; i--) {//随机数生成器,范围[0, i]int rand = (new Random()).nextInt(i+1);System.out.print(" " + rand);int temp = arr[i];arr[i] = arr[rand];arr[rand] = temp;}//置换之后的数组System.out.println("\n" + "置换后的数组:");for (int k: arr)System.out.print(" " + k);}}
分析:从运行结果可以看到随着算法的进行,可供选择的随机数范围在减小,与此同时此时数组里的元素更加趋于无序。
四、潜在的偏差
在实现Fisher-Yates费雪耶兹随机置乱算法时,可能会出现偏差,尽管这种偏差是非常不明显的。原因:一是实现算法本身出现问题;二是算法基于的随机数生成器。
1.实现上每一种排列非等概率的出现
在算法流程里 j 的选择范围是从0...i-1;这样Fisher-Yates算法就变成了Sattolo算法,共有(n-1)!种不同的排列,而非n!种排列。
j在所有0...n的范围内选择,则一些序列必须通过n^n种排列才可能生成。
2.Fisher-Yates费雪耶兹算法使用的随机数生成器是PRNG伪随机数生成器
这样的一个伪随机数生成器生成的序列,完全由序列开始的内部状态所确定,由这样的一个伪随机生成器驱动的算法生成的不同置乱不可能多于生成器的不同状态数,甚至当可能的状态数超过了排列,不正常的从状态数到排列的映射会使一些排列出现的频率超过其他的。所以状态数需要比排列数高几个量级。
很多语言或者库函数内建的伪随机数生成器只有32位的内部状态,意味着可以生成2^32种不同的序列数。如果这样一个随机器用于置乱一副52张的扑克牌,只能产生52! = 2^225.6种可能的排列中的一小部分。对于少于226位的内部状态的随机数生成器不可能产生52张卡片的所有的排列。
伪随机数生成器的内部状态数和基于此生成器的每种排列都可以生成的最大线性表长度之间的关系:
- 费雪耶兹(Fisher–Yates) 也被称作高纳德( Knuth)随机置乱算法
- 费雪耶兹(Fisher–Yates) 也被称作高纳德( Knuth)随机置乱算法
- Fisher–Yates洗牌算法
- Fisher–Yates shuffle 算法
- Fisher–Yates shuffle 算法——对给定数组进行乱序
- 洗牌算法Fisher–Yates shuffle
- 洗牌算法Fisher–Yates shuffle
- Fisher-Yates算法
- Fisher Yates 洗牌算法
- Fisher–Yates Shuffle
- Fisher–Yates shuffle算法Go语言实现
- Fisher–Yates shuffle 算法 Go 语言实现
- Fisher–Yates shuffle 算法 Go 语言实现
- 洗牌算法 数组打乱顺序 Fisher-Yates shuffle
- KMP 算法(Knuth–Morris–Pratt algorithm)
- 经典洗牌算法(Knuth-Durstenfeld Shuffle)
- 沃罗诺伊图(Voronoi Diagram,也称作Dirichlet tessellation,狄利克雷镶嵌 )归纳
- OC 中方法名为什么被称作选择器(selector)?
- 字符串/数字之间类型转换总结
- IOS内存管理retain,assign,copy,strong,weak
- 浅析Java虚拟机结构与机制
- 学习&使用技术的四种层次
- C#基础学习-交换两个数字的值
- 费雪耶兹(Fisher–Yates) 也被称作高纳德( Knuth)随机置乱算法
- 配置集群,tasktracker与datanode启动一会儿后,自动消失
- C++引用
- [转载]判别式模型和产生式模型
- Tomcat的控制台输出到文件
- 千古词帝
- 台湾行旅游与随身wifi
- I2C驱动情景分析——怎样控制I2C时序
- 让IIS 7显示ASP的详细错误信息-无论什么样的代码错误,只显示“500 - 内部服务器错误解决