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…

相關文章
相關標籤/搜索