【JavaScript】数组随机排序 之 Fisher–Yates 洗牌算法
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
三、JS源代码
//算法思想:从0~i(i的变化为 n-1到0递减)中随机取得一个下标,和最后一个元素(i)交换。
function shuffle(arr) {
var i = arr.length, t, j;
while (i) {
j = Math.floor(Math.random() * i--); //!!!
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
//console.log(arr);
}
return arr;
}
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K", "A"];
undefined
for (let i = 0; i < 100; i ++) {
shuffle(arr)
}
四、潜在的偏差
在实现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张卡片的所有的排列。
伪随机数生成器的内部状态数和基于此生成器的每种排列都可以生成的最大线性表长度之间的关系:
/**
* Randomize array element order in-place.
* Using Durstenfeld shuffle algorithm.
*/
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
} //使用ES2015(ES6) Array.prototype.shuffle = function() {
let m = this.length, i;
while (m) {
i = (Math.random() * m--) >>> 0;
[this[m], this[i]] = [this[i], this[m]]
}
return this;
}
【JavaScript】数组随机排序 之 Fisher–Yates 洗牌算法的更多相关文章
- 关于JavaScript的数组随机排序
昨天了解了一下Fisher–Yates shuffle费雪耶兹随机置乱算法,现在再来看看下面这个曾经网上常见的一个写法: function shuffle(arr) { arr.sort(functi ...
- js 数组随机排序
仅用于个人学习记录 javascript 数组随机排序1.最简洁的方法:function randomsort(a, b) { return Math.random()>.5 ? -1 : ...
- 比较两种数组随机排序方法的效率 JavaScript版
//比较2中数组随机排序方法的效率 JavaScript版 //randon1思路 //当len=5时候,从0-5中随机3一个放入i=0, // 从0-3随机一个2放入i=2 // 从0-2随机一个1 ...
- Fisher–Yates shuffle 洗牌算法(zz)
1,缘起 最近工作上遇到一个问题,即将一组数据,比如[A,B,C,D,E]其中的两个B,E按随机排列,其他的仍在原来的位置: 原始数组:[A,B,C,D,E] 随机字母:[B,D] 可能结果:[A,B ...
- javascript数组对象排序
javascript数组对象排序 JavaScript数组内置排序函数 javascript内置的sort函数是多种排序算法的集合 JavaScript实现多维数组.对象数组排序,其实用的就是原生的s ...
- JS数组随机排序
var arr=[1,2,3,4,5]; arr.sort(function(a,b){ var v=Math.random()>0.5?1:-1; console.log(a,b,v); re ...
- random array & shuffle 洗牌算法 / 随机算法
random array & shuffle shuffle 洗牌算法 / 随机算法 https://en.wikipedia.org/wiki/Fisher–Yates_shuffle ES ...
- 《Algorithms算法》笔记:元素排序(3)——洗牌算法
<Algorithms算法>笔记:元素排序(3)——洗牌算法 Algorithms算法笔记元素排序3洗牌算法 洗牌算法 排序洗牌 Knuth洗牌 Knuth洗牌代码 洗牌算法 洗牌的思想很 ...
- 随机洗牌算法Knuth Shuffle和错排公式
Knuth随机洗牌算法:譬如现在有54张牌,如何洗牌才能保证随机性.可以这么考虑,从最末尾一张牌开始洗,对于每一张牌,编号在该牌前面的牌中任意一张选一张和当前牌进行交换,直至洗到第一张牌为止.参考代码 ...
随机推荐
- Codeforces 349C - Mafia
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- Codeforces 592D - Super M - [树的直径][DFS]
Time limit 2000 ms Memory limit 262144 kB Source Codeforces Round #328 (Div. 2) Ari the monster is n ...
- HDU 2444 - The Accomodation of Students - [二分图判断][匈牙利算法模板]
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2444 Time Limit: 5000/1000 MS (Java/Others) Mem ...
- Redis used_cpu_sys used_cpu_user meaning (redis info中cpu信息的含义)
Redis 中 used_cpu_sys 和 used_cpu_user含义. 在Redis的info命令输出结果中有如下四个指标,redis官网给出了下面一段解释,但是还是不明白什么意思. used ...
- SCRAM
RFC 5802 - Salted Challenge Response Authentication Mechanism (SCRAM) SASL and GSS-API Mechanisms ht ...
- iOS-多语言版本的开发(一)(转载)
引言 多语言 & 本地化,随你怎么叫,道理差不多:一个App 要想走出国门,只支持一种语言是不能够的,也是不可能的,多元化世界已经融入我们的生活,对于一些应用,开发多语言版本,已经是不可避免 ...
- 自定义maven插件
之前虽然一直知道maven插件是可以自定义的,不过一致没有用过.最近接触到了swagger项目中的codegen自动生成代码的功能,并且在codegen源码中,也是存在maven插件功能的,所以自己就 ...
- grpc protobuf
1.ProtoBuffer是google的一款非常高效的数据传输格式框架 2.一个方法仅能接受一个参数 3.对于定义的message,每个值都有一个唯一的number类型的数字,根据官方文档的解释:它 ...
- 优云亮相GOPS2017全球运维大会 “黑科技”获全场最高关注
2017年4月21日,GOPS――2017全球运维大会于深圳・圣淘沙酒店拉开帷幕.GOPS全球运维大会由高效运维社区(GreatOPS)和开放运维联盟(OOPSA)联合主办,由工信部信通院数据中心联盟 ...
- 洛谷P2602 数字计数 [ZJOI2010] 数位dp
正解:数位dp 解题报告: 传送门! 打算在寒假把学长发过题解的题目都做辣然后把不会的知识点都落实辣! ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄ 然后这道题,开始想到的时候其实想到的是大模拟,就有点像之前考试贪 ...