详解快速排序

简介

快速排序是一种应用广泛且高效的排序算法

快速排序采用的是分治的思想,分而治之,例如:当需要对一个整型数组排序时,可以在区间内找一个数作为基准值,将比这个数小于或者等于的数都放在左边,比这个数大于或者等于的数都放在右边,然后再对左边和右边重复执行刚刚的操作,用递归来实现,直到区间内只有1个数或者没有数,这时,区间就排完序了,当所有的区间都排完序,那么这个数组就排完序了

那么这个数该取区间内的哪个呢?一般来说有4种,1.区间的第一个数 2.区间的最后一个数 3.区间中间的数 4.随机一个数

我们先来看看快速排序的动态图:其中P就是区间内找的一个基准数,P找的是区间中的最后一个数,以它为基准将区间分为两半,左边都是小于等于P的,右边都是大于等于P的,再对左边的区间重复操作...

我们先来看一下快排的模版

void quick_sort(int p[],int l,int r)
{
	if(l>=r)    //递归结束的条件,区间内已经是顺序了
	return;     
	int x=p[l];    //x是基准值,与动图的不同,取的是区间中第一个元素
    int i=l-1,j=r+1; 
	while(i<j)
	{     
		do(i++);while(p[i]<x);
		do(j--);while(p[j]>x); 
		if(i<j) swap(p[i],p[j]);  // 得检查i和j是否已经互相穿过
	}
		quick_sort(p,l,j);   
		quick_sort(p,j+1,r);
}

其中l和r是区间的下标,那为什么i不等于l,j不等于r呢?可以这么想当交换完两个数之后,不管怎么样i和j至少要移动一步,那怎么样可以实现这个呢,可以使用do-while来保证程序正常运行,不过也可以这样写

while(p[++i]<x);
while(p[--j]>x);

如果不使用上面这两种方法,而使用了下面这种,就会有一种情况,如果i和j指向的两个数相同,那么就会出现死循环

i=l,j=r;
while(p[i--]<x);
while(p[j--]>x);

接下来也就是最难处理的问题了

边界问题

如果我们在循环过程中的交换条件中使用<=和>=,会出现以下情况:当选取的基准值为区间内最大的数,那么这个q[i]<=x在这个区间内是恒成立的,会造成越界,又或者这个基准值是区间内最小的值,那么q[j]>=x也是恒成立的,也是同样的结果

因此,在快速排序算法中,通常会采用严格的<和>操作符来避免这种情况的发生。

举个例子:如果用了<=和>=

3  4  5      基准值为3,i=0,j=2

3  4  5        i=?,j=2;

还有为什么当使用x=q[l]时,递归的区间是[l,j]和[j+1,r]?

x=q[l]的边界情况
当只有两个元素时例如1,2,这时按照代码执行下来,循环之前i=l,退出循环后quick_sort(l,i-1),quick_sort(i,r);等价于quick_sort(l,i-1),quick_sort(l,r);这就跟进入递归时一样了,就导致了死循环,所以此时只能用sort(l,j),sort(j+1,r);
x = q[r]的边界情况
道理类似,如果此时为2,1也会导致j=r,进行sort(l,j),sort(j+1,r);导致死循环(一直sort(l,r),此时只能用sort(l,i-1),sort(i,r);
x=q[l+r>>1]的边界情况
此时x取的是序列中间靠左的位置(如果序列个数为奇,则取正中间,如果为偶,则取中间靠左),此时如果元素个数为2,
则中间靠左就是第1个元素,这时就跟x=q[l]的边界情况一致了,所以这时只能用sort(l,j),sort(j+1,r);
x=q[l+r>>1]的边界情况
此时x取的是序列中间靠右的情况,同理,当元素只有两个,情况就会类似x=q[r],此时只能用sort(l,i-1),sort(i,r);
总结:
如果x=q[l] or x=q[l+r>>1]此时只能用sort(l,j),sort(j+1,r);
如果x=q[r] or x=q[l+r + 1>>1]此时只能用sort(l,i-1),sort(i,r);

有时候基准值x采用区间内随机一个值,能够更好地完成工作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值