本文收集了幾種經常使用排序方式的JS代碼實現與性能比較,包括:冒泡排序,選擇排序,插入排序,歸併排序和快速排序,咱們從實現方式最簡單的冒泡排序入手javascript
1、冒泡排序html
原理:依次比較兩個相鄰的項,若是前者大於後者,則交換二者位置,就如同氣泡往上冒同樣。java
代碼實現:數組
Array.prototype.bubbleSort = function(){ var length = this.length; for(var i=0;i<length;i++){ for(var j=0;j<length-1-i;j++){ this[j]>this[j+1] && swap(this,j,j+1) //swap方法交換兩個元素 } } }
注意,內層循環的次數須要減掉外層已循環過的次數,由於外層循環每走一遍就有一個元素被排好序,無需再進行排序。瀏覽器
這種排序方式的時間複雜度爲O(n^2),(時間複雜度的計算方法參見http://baike.baidu.com/link?url=DnQgmILQ4dt2kCRwafBtNJHo21upzQVZAX2Y6TyJLoh2rxy_YQtxfhjwhmHmneETaSlw9KuKCjzSJqwGtzL4CUSm4aC3mYTfDlsjfZWCRFiQ8TiPnKHvn3mZ6-YpTkAYX1MEn5BRoFmjOHFRjzNCSK)函數
,咱們能夠在http://math.hws.edu/eck/js/sorting/xSortLab.html中模擬這個過程,結果以下:性能
執行10個長度爲10000的亂序數組的排序,總耗時爲28.7秒ui
2、選擇排序this
原理:從數組中找到最小值,與數組首位交換位置(即放在第一位),接着再尋找第二小的值,放在第二位,以此類推url
代碼實現:
Array.prototype.selectSort = function(){ var length = this.length, minIndex; for(var i =0;i<length-1;i++){ minIndex = i; for(var j=i;j<length;j++){ if(this[minIndex]>this[j])minIndex = j; } i !== minIndex) && swap(this,i,minIndex); //swap方法交換兩個元素 } }
這種排序方式的時間複雜度爲O(n^2),模擬排序結果以下:
執行10個長度爲10000的亂序數組的排序,總耗時爲17.7秒
3、插入排序
插入排序分爲直接插入排序,二分插入排序和希爾排序,這裏介紹的是直接插入排序
原理:將數列的第一個元素視爲有序數列,後面都視爲無序數列:
{{a1},{a2,a3,a4,…,an}}
而後將無序數列中的元素插入到有序數列的對應位置,插入前經過比大小的方式找到其在有序數列中的對應位置。
Array.prototype.insertSort = function(){ var length = this.length, j, temp; for(var i=1;i<length;i++){ j = 1; temp = array[i]; //temp爲待排序項 while(j>0 && array[j-1] > temp){ array[j] = array[j-1]; j--; } //若temp項以前存在比temp大的項,則把這個項移到當前位置上, //直到找不到比temp更大的項時, array[j] = temp //執行插入操做 } }
這種排序方式的時間複雜度爲O(n^2),模擬排序結果以下:
執行10個長度爲10000的亂序數組的排序,總耗時爲8秒
4、歸併排序
從這裏開始纔是真正能投入實際使用的排序方法,包括最後的快速排序,瀏覽器通常使用這兩種方法之一做爲sort函數的實現(可是V8對較短的數組使用插入排序方法)
原理:歸併排序採用分治--遞歸的思想,先對一個數組進行不斷的對半拆解,直至子項個數爲1。如圖:
(原圖:http://www.108js.com/article/article5/img/1.png)
以後執行合併,從最下層開始,依次比較左邊的項是否比右邊的小,是的話移除左數組的第一位並放進新數組中,不然移除右數組的第一位並放進新數組中,這樣就能夠從新合併出一個排完序的大數組。
代碼實現:
function merge(left, right) { var result = []; while(left.length > 0 && right.length > 0) { if(left[0] < right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } // 當左右數組長度不等.將比較完後剩下的數組項連接起來便可 console.log(result) return result.concat(left).concat(right); } function mergeSort(array) { if(array.length == 1) return array; // 對半劃分 var mid = Math.floor(array.length / 2); var left = array.slice(0, mid); var right = array.slice(mid); // 遞歸合併 return merge(mergeSort(left), mergeSort(right)); }
這種排序方式的時間複雜度爲O(n*log n),模擬排序結果以下:
能發現歸併排序對大數組的排序效率已經有了質的提高
5、快速排序
原理:首先選取一個基準項(pivot),咱們通常選取中間項做爲pivot;接着全部小於"基準"的元素,都移到"基準"的左邊;全部大於"基準"的元素,都移到"基準"的右邊。而後對"基準"左邊和右邊的兩個子集,不斷重複第一步和第二步,直到全部子集只剩下一個元素爲止
代碼實現:
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++){ if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right)); };
這裏參考了阮一峯老師的文章,詳情可移步
http://www.ruanyifeng.com/blog/2011/04/quicksort_in_javascript.html
這種排序方式的時間複雜度爲O(n*log n),模擬排序結果以下:
與歸併排序很接近,對於快速排序與歸併排序的性能比較,可參考如下文章:
http://stackoverflow.com/questions/680541/quick-sort-vs-merge-sort