JavaScript tips —— 谈谈数组乱序


前言

先看一个段代码
git

function randArr (arr) {
    return arr.sort(() => {
        return (Math.random() - 0.5);
    });
}复制代码

目的是为了实现给定数组的乱序。github

利用数组的sort方法,判断随机出来的0~1的值与0.5的大小,实现伪排序。web

为何说是伪排序呢?代码的逻辑没毛病啊。算法

对,从这个层面来看,简单明了,完美的实现了需求,本着凡事往祖坟刨得精神。来看看这段代码的内部实现。segmentfault

浏览器实现

ECMA Script

The elements of this array are sorted. The sort is not necessarily stable (that is, elements that compare equal do not necessarily remain in their original order). If comparefn is not undefined, it should be a function that accepts two arguments x and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y.

大体说的意思是,我无论你排序的算法稳不稳定,反正你能给用户自定义排序规则就行,不给你就爱咋折腾咋折腾~数组

这帮浏览器一听,好啊,老大发话了,那就八仙过海各显神通,各自都认为本身的实现是最牛逼的。浏览器

Chrome的sort

基于V8引擎,它的排序算进行了不少的优化,可是核心是小于等于10的数组用插入排序(稳定),大于10的采用了quickSort(不稳定),源码bash

FireFox的sort

基于SpiderMonkey引擎,采用了归并排序(稳定), 源码dom

Safari的sort

基于Nitro(JavaScriptCore )引擎,若是没有自定义的排序规则传入,采用桶排序(不必定稳定, 桶排序的稳定性取决于桶内排序的稳定性, 所以其稳定性不肯定。),传入自定义规则,采用归并排序(稳定),源码ide

Microsoft Edge/IE9+

基于Chakra引擎,采用快排(不稳定)源码

好了,那个说sort能够不是伪排序的同窗,你看见我这40米的大刀没?

什么,你还嘴硬,我喜欢你的性格,看下面:

github上的大神对 var letters = ['A','B','C','D','E',‘F’,‘G’,'H','I','J'];

进行了10000次乱序处理,发现结论: 元素大几率停留在本身的初始位置。

具体地址: HOUCe/shuffle-array

看见没,矮要认可,挨打要立正。

洗牌算法(Fisher-Yates)

想要实现真正意义上的乱序,咱们来研究一下:只要知足每一个元素出如今各个位置的几率同等便可。

少年,听过如来神掌吗?

有个Fisher-Yates的洗牌算法,知足您的各类乱序需求,物美价廉,杀人越货居家旅行的必备精品~(其实有三个版本,有兴趣的自行搜索)

算法的大体描述

1.找到数组的屁股(最后一个元素);

2.在脑壳和屁股中间随机一个位置;

3.交换元素;

4.这时屁股是已经乱序后的元素,因此屁股前移;

5.若是屁股没打到脑壳上就继续1~4的步骤

function shuffle(arr) {
    let length = arr.length,
        r      = length,
        rand   = 0;

    while (r) {
        rand = Math.floor(Math.random() * r--);
        [arr[r], arr[rand]] = [arr[rand], arr[r]];
    }

    return arr;
}复制代码

参考文献

github.com/HOUCe/shuff…

en.wikipedia.org/wiki/Fisher…

efe.baidu.com/blog/talk-a…

segmentfault.com/a/119000001…

相关文章
相关标签/搜索