经常使用排序算法的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

相关文章
相关标签/搜索