怎样让快速排序(quick sort)更快?

 

快速排序(quick sort)是目前应用最广泛的排序算法,它的平均复杂度为O(NlogN),但因其内循环较小,所以速度很快,而且不需要太多额外的空间(主要是递归调用所需的栈空间,对于随机文件不大于logN)。关于算法的基础介绍,网上已有很多讲解得很好的资料,如July同学的快速排序算法》,我就不拾人牙慧了,切入正题。

 

快速排序有点像二分搜索(binary search):思想很简单,算法很高效,大家都知道,实现很困难。快速排序的一大特点就是效率不稳定,运行时间与输入数据密切相关,原因在于,快排是基于划分(partition)的排序算法,划分操作决定了整个算法的效率。许多简单实现中,划分的基准(pivot)都取输入序列中的第一个或最后一个元素。对于随机数据而言,这是足够有效的;但对于已经有序或者逆序的数据,这种划分将导致快速排序的时间效率退化成O(N2),空间使用也会达到O(N)。可见一个好的划分过程对快速排序多么重要,因此第一个加速就从划分开始。

 

划分(partition)

划分操作中有两个值得关注的方面:

  • 划分的过程
  • 划分的基准

快排中移动元素的实际操作由划分完成,因此划分过程必须快速。目前已知的一个非常高效的算法,通过从数组两端向中间扫描的方法来完全划分。

                    

 

令划分的基准v放在数组最右边,指针ileft开始向右扫描,遇到大于v的值则停住;同时令指针jright-1开始向左扫描,遇到小于v的值时停下来,交换ij指向的值,然后重复上述过程,直至ij相遇。

该算法维护了一个不变式:i左边的元素都小于vj右边的元素都大于v。这个策略是线性时间地原地划分,只扫描数组一次就能完成,C++实现如下(请仔细斟酌):

 

	template <typename Item>
	int partition(Item a[], int left, int right) {
	  int i = left-1, j = right;
	  Item v = a[right];
	  for (;;) {
	    while (a[++i] < v) {}
	    while (a[--j] > v)
	      if (j == left)
	        break;
	    if (i >= j)
	      break;
	    exchange(a[i], a[j]);
	  }
	  exchange(a[i], a[right]);
	  return i;
	}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值