前言
先看一個段程式碼
function randArr (arr) {
return arr.sort(() => {
return (Math.random() - 0.5);
});
}複製程式碼
目的是為了實現給定陣列的亂序。
利用陣列的sort方法,判斷隨機出來的0~1的值與0.5的大小,實現偽排序。
為什麼說是偽排序呢?程式碼的邏輯沒毛病啊。
對,從這個層面來看,簡單明瞭,完美的實現了需求,本著凡事往祖墳刨得精神。來看看這段程式碼的內部實現。
瀏覽器實現
ECMA Script
大致說的意思是,我不管你排序的演算法穩不穩定,反正你能給使用者自定義排序規則就行,不給你就愛咋折騰咋折騰~
這幫瀏覽器一聽,好啊,老大發話了,那就八仙過海各顯神通,各自都認為自己的實現是最牛逼的。
Chrome的sort
基於V8引擎,它的排序算進行了很多的優化,但是核心是小於等於10的陣列用插入排序(穩定),大於10的採用了quickSort(不穩定),原始碼。
FireFox的sort
基於SpiderMonkey引擎,採用了歸併排序(穩定), 原始碼
Safari的sort
基於Nitro(JavaScriptCore )引擎,如果沒有自定義的排序規則傳入,採用桶排序(不一定穩定, 桶排序的穩定性取決於桶內排序的穩定性, 因此其穩定性不確定。),傳入自定義規則,採用歸併排序(穩定),原始碼
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;
}複製程式碼