經常使用排序算法的JavaScript實現與性能比較

本文收集了幾種經常使用排序方式的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

相關文章
相關標籤/搜索