如何將一個JavaScript數組打亂順序?

由抽牌、換牌和插牌衍生出三種洗牌算法,其中分別對應Fisher-Yates Shuffle、Knuth-Durstenfeld Shhuffle、Inside-Out Algorithm算法

今天介紹Fisher-Yates Shuffle洗牌算法。最早提出這個洗牌方法的是 Ronald A Fisher 和 Frank Yates,即 Fisher–Yates Shuffle,其基本思想就是從原始數組中隨機取一個之前沒取過的數字到新的數組中。

下面證明其隨機性,即每個元素被放置在新數組中的第i個位置是1/n(假設數組大小是n)。

證明:一個元素m被放入第i個位置的概率P = 前i-1個位置選擇元素時沒有選中m的概率 * 第i個位置選中m的概率,即:

具體如下,我們簡單藉助圖形來理解,非常簡單直觀。你接下來就會明白爲什麼這是理論上的完全亂序(圖片來源於網絡)。

首先我們有一個已經排好序的數組:

Step1:
第一步需要做的就是,從數組末尾開始,選取最後一個元素。

在數組一共 9 個位置中,隨機產生一個位置,該位置元素與最後一個元素進行交換。

Step2:
上一步中,我們已經把數組末尾元素進行隨機置換。



接下來,對數組倒數第二個元素動手。在除去已經排好的最後一個元素位置以外的8個位置中,隨機產生一個位置,該位置元素與倒數第二個元素進行交換。

Step3:
理解了前兩部,接下來就是依次進行,如此簡單。

最後,我們實現代碼:

Array.prototype.shuffle = function() {
    var array = this;
    var m = array.length,
        t, i;
    while (m) {
        i = Math.floor(Math.random() * m--);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
    }
    return array;
}

將當前元素和隨機選出的下標所指的元素互相交換,其中選取下標範圍的依據在於每個被摸出的元素都不可能再被摸出來了。此外還有一個需要注意的細節,當前元素是可以和它本身互相交換的 - 否則生成最後的排列組合的概率就不對了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章