Fisher–Yates shuffle 洗牌算法


1,緣起

最近工作上遇到一個問題,即將一組數據,比如[A,B,C,D,E]其中的兩個B,E按隨機排列,其他的仍在原來的位置:

原始數組:[A,B,C,D,E]

隨機字母:[B,D]

可能結果:[A,B,C,D,E],[A,D,C,B,E]

在解決這個問題的過程中,需要解決的一個問題是,怎么樣讓一個數組隨機排序?上網一查,這也是計算機科學基礎問題,也稱之為洗牌算法(Shuffle Algorithm)。

 

2,問題及解決

2.1,問題

很簡單:給定一個數組,將其中的元素隨機排列。比如給定數組arry=>[1,2,3,4,5]。有A5-5種結果即5!=120種結果

 

2.2,解決

也很簡單,如果用白話來說就是:

a,選中第1個元素,將其與n個元素中的任意一個交換(包括第1個元素自己)。這時排序后的第1個元素已經確定。

b,選中第2個元素,將其與n-1個元素中作任意一個交換(包括第2個元素自己)。

c,重復上面步驟,直到剩1個元素為止。

 

3.3,代碼

知道其算法了,實現就簡單了:

/// <summary>
/// Randomize the list elements using Fisher–Yates shuffle algorithm http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
/// </summary>
/// <typeparam name="T">elements type</typeparam>
/// <param name="list"></param>
public static void Shuffle<T>(this IList<T> list)
{
    Random rng = new Random();
    int n = list.Count;
    while (n > 1)
    {
        n--;
        int k = rng.Next(n + 1);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}

 

3.4,其它

該算法復雜度為O(n),且無偏差,各個元素隨機概率相等。確實是一個好算法:)。

在Wiki上,還有一些該算法的變種,但還是上面講的那種比較好用,最初的Fisher–Yates算法並不好用,復雜度為O(n^2)。

 

參考:

http://blog.codingnow.com/2007/09/shuffle.html

http://en.wikipedia.org/wiki/Fisher-Yates_shuffle


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM