常見的音樂隨機播放算法主要有兩種:一是Shuffle算法;二是Random算法。
一 Shuffle算法
Shuffle算法和排序算法正好相反,是從有序到亂序的一個過程,俗稱洗牌算法。它將播放列表中的歌曲順序打亂,變成一個和原來歌曲順序沒有任何關系的亂序的播放列表,之后進行歌曲的播放,並支持當用戶點擊“上一首”時,能夠回到剛剛播放的那一首歌曲。
二 Random算法
Random算法是在選取即將播放的歌曲時,進行一個隨機數的運算,得到即將播放的歌曲在播放列表中的索引,播放列表本身並沒有被打亂,只是利用隨機函數從播放列表中選取一首歌曲進行播放而已。
現在比較普遍的隨機數生成算法是基於線性同余算法實現的,例如C語言標准庫函數rand()就是利用它產生隨機數的。線性同余算法能夠產生均勻分布的隨機數,但是它依賴於給定的隨機數的上限,如果上限越小,產生的隨機數重復的概率就越大。
Random算法另一個缺陷是當點擊“上一首”時,跟“下一首”功能完全一樣,都是重新生成隨機數,並利用它從播放列表中選取歌曲進行播放,而不會回到剛剛播放的那一首歌。當然,這個缺陷可以通過提供歷史記錄來彌補,只是需要花費額外的空間。
三 隨機函數
上面兩種算法的關鍵都是隨機函數,下面介紹Java和C兩種語言中隨機函數的使用。
3.1)Java中的隨機函數
Java是采用線性同余算法產生隨機數的,優點是隨機性好,周期長,速度快,易於計算機軟件實現,缺點是產生的隨機數受數學規律的制約,具有周期性和相關性,只能產生偽隨機序列。JDK提供的隨機數生成方式有兩種:
3.1.1)Math.random()函數
該函數返回0到1區間中的某個double值,源碼實現如下:
可見,該函數底層是調用Random類實現的,首次調用random函數時,靜態成員變量randomNumberGenerator為空,因此將調用Random類的構造函數進行初始化,隨后每次調用random函數randomNumberGenerator不再為空,將不會再實例化Random類,因此,每次調用Math.random()函數用到的都是同一個種子,也就是首次調用的系統時間產生的種子。3.1.2)Random類
位於Java.util包中,該類有兩個構造函數,實現如下:
可見,構造函數默認使用當前的系統時間產生種子,用於初始化Random對象。之后就可以調用各種next*函數來獲取各種類型的隨機數,如nextBytes,nextInt,nextDouble,nextGaussian等等。
3.2)C/C++中的隨機函數
C/C++中最常用的生成偽隨機數的方法是C標准庫提供的rand()函數,它定義在stdlib.h文件中,能夠返回0~RAND_MAX之間均勻分布的偽隨機數(RAND_MAX至少為32767,一般默認為32767)。
直接調用rand(),每次生成的偽隨機序列是相同的,因為rand()在生成隨機數時會使用一個種子(默認值是1),作為計算隨機數的初始值,如果種子相同,那么生成的偽隨機序列也將是一樣的。解決的辦法很簡單,就是每次使用不同的種子來調用rand()函數,srand()函數就是用來設置rand()函數產生隨機數時使用的種子的。
srand()函數原型如下:
srand()和rand()配合使用的示例如下:
需要注意的一點是,上面代碼在生成多個隨機數時,要將srand()放到for循環的外面,否則上面輸出的10個隨機數都將是一樣的,因為計算機運行速度太快,導致time()函數執行的結果沒來得及改變。詳見下圖。

四 音樂隨機播放算法的Shuffle實現
4.1)C/C++版本
4.2)Java版本
五 現成的Shuffle庫算法
其實無論在C++還是Java中,都已經實現了Shuffle算法,在實際項目開發中,如果不是有特殊要求的話,完全沒有必要自己去實現Shuffle算法,下面就來看看已有的Shuffle算法。
5.1)C++中的Shuffle算法
C++ STL中的函數random_shuffle()就是用來對一個元素序列進行隨機重新排序的算法,函數原型如下:
具體用法可參見:http://blog.csdn.net/ACE1985/article/details/5868682 。
5.2)Java中的Shuffle算法
Collections類中實現了Shuffle算法,這個類位於java.util包中,有兩個重載函數,下面直接看源碼:
參考文獻:
1)http://www.ifanr.com/29498 從隨機播放算法看iPod的細節之美
2)http://blog.csdn.net/cstn_kdlx/article/details/7326516 隨機數生成問題小結
3)http://blog.csdn.net/hcy0727/article/details/7581671 洗牌算法
4)http://blog.csdn.net/chosen0ne/article/details/6129315 隨機播放CD
5)http://blog.csdn.net/ACE1985/article/details/5868682 random_shuffle()和transform算法