一、常規算法算法
function shuffle(array) { var copy = [], n = array.length, i; while(n) { i = Math.floor(Math.random() * array.length); if (i in array) { copy.push(array[i]); delete array[i]; n--; } } return copy; }
這個方法有個很大的問題在於: delete array[i] 會將array的第i個元素設置爲空,即刪除後的值爲undefined,而數組長度並不會改變,因此每次隨機的時候頗有可能還會隨機到這個序號,雖然代碼中有if(i in array) 來避免空值存入新數組,可是徒增了沒必要要的循環,下降了效率;而且還有會存在永遠運行不完的可能!由於隨機數有可能一值會隨機到已經置空的數據!數組
這個方法不是太可取!dom
二、改進的作法性能
function shuffle(array) { var copy = [], n = array.length, i; while (n) { i = Math.floor(Math.random() * n--); copy.push(array.splice(i, 1)[0]); } return copy; }
此方法的重點在於 array.splice(i, 1)。即將隨機出來的數據從原數組中剔除,這樣下一次隨機的時候就不可能會取到這個值了!而且n--保證了循環不會永遠運行!
優化
不過,該方法splice刪除數組元素會致使刪除位置以後的全部元素要作shift操做來向前補充,增長了算法的複雜度。spa
三、進一步優化code
function shuffle(array) { 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; }
由於咱們要的目的是打算數組的排序,因此打亂後的數組的長度應該是跟原數組長度同樣的,因此,隨機從數組中抽出一個元素,而後與最後一個元素交換,至關於把這個隨機抽取的元素放到數組最後面去,表示它已經被隨機過了,同時被換走的那個元素(原來在最後的那元素)跑到前面去了,會在後續的重複操做中被隨機掉。一輪操做事後,下一輪咱們只在剩下的n-1個元素中進行相同的操做,直到隨機到第一個。blog
附加:排序
function shuffle(array) { return array.sort(function(){ return Math.random() - 0.5; }); }
結合js自帶的sort() 方法來實現,這個方法雖然看似簡潔不少(其實只是js後臺運行,源碼sort()方法十分複雜),可是性能卻不如上面那種方法!由於隨着數組元素越多,其隨機性會變差。源碼