【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张牌,如何洗牌才能保证随机性.可以这么考虑,从最末尾一张牌开始洗,对于每一张牌,编号在该牌前面的牌中任意一张选一张和当前牌进行交换,直至洗到第一张牌为止.参考代码 ...
随机推荐
- vue--点击事件
<template> <div id="app"> <p>{{msg}}</p> <input type="text ...
- ajax跨域获取返回值
js代码 $.ajax({ async:false, url: 'https://***/api/prepareApi.getDanMu?sqlMapId=findBarrage', // 跨域URL ...
- css实现表格的td里面的内容居中.
<td align="center" valign="middle">前一个是水平居中 后一个是垂直居中对应的css写法:<td style= ...
- uva 10983 Buy one, get the rest free 二分判定层次图
二分枚举租用飞机的最大花费,然后用小于等于最大花费的边构建层次图(依据时间) 构图思路: 利用二元组(x,y)表示 x天y城市 1. e天有飞机从a城市飞到b城市,能够承载x人,则添加单向边 ( ...
- UVA 11168 - Airport - [凸包基础题]
题目链接:https://cn.vjudge.net/problem/UVA-11168 题意: 给出平面上的n个点,求一条直线,使得所有的点在该直线的同一侧(可以在该直线上),并且所有点到该直线的距 ...
- is_file file_exists microtime performance
对项目中旧代码的疑问 } elseif (substr($class_name, 0, 6) == 'OAuth2') { $file_name = $C->INCPATH . 'classes ...
- prometheus and collectd and docker
sudo docker run --name prometheus -d -v /data/prometheusdata/prometheus.yml:/etc/prometheus/prometh ...
- Spring Boot中的自定义start pom
start pom是springboot中提供的简化企业级开发绝大多数场景的一个工具,利用好strat pom就可以消除相关技术的配置得到自动配置好的Bean. 举个例子,在一般使用中,我们使用基本的 ...
- Python实现简单HTTP服务器(一)
一.返回固定内容 # coding:utf-8 import socket from multiprocessing import Process def handle_client(client_s ...
- 网页设计师必知的10则SEO
如今,Web设计师在设计Web外观与风格的同时,往往还负责了前端代码的编写.换???话说,SEO的相当一部分责任是落在他们肩上的.然而,大 量的 Web设计师对SEO的熟悉程度仍不足以让他们写出一个符 ...