`

quick sort

阅读更多
quicksort

------
quicksort overview

quicksort 在实际应用中 非常出色,

时间复杂度:
      理论上最差是:O(n^2),
      实际应用中:平均可达到 O(n * lg(n)),且其中的 常量 比较小,

空间复杂度:
      空间占用比较小,有优势,
      即使在 虚拟内存中 也运行得较好,

------
quicksort 原理

quicksort 采用 divide-conquer 方法,

分3步:
* divide
      将 A[p .. r] 分解为 A[p .. q-1] 和 A[q+1 .. r] 2个子数组,分解函数称为 partition,
      2个子数组 满足:
            A[p .. q-1] 中所有元素 <= A[q],
            A[q+1 .. r] 中所有元素 >= A[q],
* conquer
      对2个子数组,递归调用 partition ,进行分解,
* combine
      合并子数组,从底到上合并时,都是排过序的,因此不需要额外操作,直接合并即可,
*

partition 分解 函数:
      取最后1个值作为中间值,前面的值依次和该值比较,然后决定放到该值的前面还是后面,
      当然可以根据实际情况,决定取哪个值作为分隔值,基本原则是 balance,即 所取的值可以将数组分隔为大小相近的2个子数组,

------
性能

性能取决于 分割点是否平衡,即 分割点的值在被分割数组中是否处于中间,
越平衡性能就越好,越不平衡性能越差,

最差性能是 O(n^2):
      每次分割点都是 最大 或 最小值 时发生,

最好性能是 O(n*(lg n))
      分割点每次都是 中间值时发生,

平均性能:
      在实际应用中,quicksort 的性能更接近于 最好性能 O(n*(lg n)),


------
例子

* js (quick_sort.js)
var arr_quicksort = [ 78, 13, 6, 177, 26, 90, 288, 45, 62, 83 ];

/**
 * quict sort<br />
 * <pre>
 * <b>思路:</b>
 * 	divide-and-conquer, 
 * 	将数组 分成 左中右 3部分,左右是2个数组,左数组所有值 <= 中间值,右数组所有值 >= 中间值,
 * 	直到最后所有值都被分解为单个值,而且已经是排过序的,
 * </pre>
 * <b>时间复杂度:</b>理论上最差是 O(n^2),实际应用中是 O(n * (lg n)),且常量系数较小<br />
 * <b>空间复杂度:</b>O(n),即使在虚拟内存中也运行良好<br />
 * 
 * @author kuchaguangjie
 * @date 2011年1月1日
 * @return
 */
function QuickSort(initArr) {
	this.totalCount = initArr.length;
	this.tmpArr = [ initArr ];
	this.resultArr = [];
}
/**
 * 排序调用入口
 * 
 * @return
 */
QuickSort.prototype.sort = function() {
	while (this.resultArr.length < this.totalCount) {
		this.partition();
	}
	return this.resultArr;
};
/**
 * 将1个数组 分成 左中右 3块,满足:左 <= 中 <= 右,并将3块放到1个数组返回,
 * 
 * @param arr
 *            待分解的数组
 * @return
 */
QuickSort.prototype.partitionSingle = function(arr) {
	if (arr.length <= 1) {
		return arr;
	}

	var partLeftArr = [];
	var partRightArr = [];
	var partMiddle = arr[arr.length - 1]; // 最后1个元素,用作分隔值
	for ( var i = 0; i < arr.length - 1; i++) {
		if (arr[i] <= partMiddle) {
			partLeftArr[partLeftArr.length] = arr[i];
		} else {
			partRightArr[partRightArr.length] = arr[i];
		}
	}

	var partArr = [];
	if (partLeftArr.length > 0) {
		if (partLeftArr.length == 1) {
			partArr[0] = partLeftArr[0];
		} else {
			partArr[0] = partLeftArr;
		}
	}
	partArr[partArr.length] = partMiddle;
	if (partRightArr.length > 0) {
		if (partRightArr.length == 1) {
			partArr[partArr.length] = partRightArr[0];
		} else {
			partArr[partArr.length] = partRightArr;
		}
	}
	return partArr;
};
/**
 * 对整个数组做1次 partition
 * 
 * @return
 */
QuickSort.prototype.partition = function() {
	this.resultArr = [];
	for ( var i = 0; i < this.tmpArr.length; i++) {
		if (QuickSort.prototype.isArray(this.tmpArr[i])) { // 是 array 则分解
			var partArr = this.partitionSingle(this.tmpArr[i]);
			for ( var j = 0; j < partArr.length; j++) {
				this.resultArr[this.resultArr.length] = partArr[j];
			}
		} else { // 单个数字
			this.resultArr[this.resultArr.length] = this.tmpArr[i];
		}
	}
	if (this.resultArr.length < this.totalCount) {
		this.tmpArr = this.resultArr.slice(0, this.resultArr.length);
	}
};

/**
 * 检验是否是 Array
 * 
 * @param v
 * @return
 */
QuickSort.prototype.isArray = function(v) {
	return Object.prototype.toString.apply(v) === '[object Array]';
}


* html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="js/quick_sort.js"></script>
</head>
<body>
<input type="button" value="quick sort" onclick="alert(new QuickSort(arr_quicksort).sort());" />
</body>
</html>


*

------
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics