这是C++算法基础-基础算法专栏的第二篇文章,专栏详情请见此处。
引入
对于在一个数组中寻找第大的数问题中,如果直接用快速排序将数组排序再去查找来做,那么时间复杂度就是
了,对于这个问题来说不太划算。而用快速选择算法实现,时间复杂度就可以降为
。
下面我们就来讲快速选择算法的实现。
定义
快速选择算法,又称找第大的数(K-th order statistic)问题。
过程
快速选择算法的工作原理与快速排序是一样的。共分为三个过程:
- 将数列划分为两部分;
- 递归到两个子序列中分别进行排序;
- 按照分界点和
的大小关系来判断是只在哪一边递归求解即可,然后重复执行上述步骤,直到递归到边界。
第一、二步与快速排序的步骤相同,详情可见快速排序的实现。
第三步,两个子序列排序完成后,若当前分界点在下标处,那么当前序列就分成了
与
两个序列,这时我们只用按照
与
的关系,就可以判断要在哪个子序列递归求解。具体来说,若
,我们就在
中求解,反之就在
中求解。
注意,我们需要判断只是在其中的哪一个子序列中递归求解!并不需要两个子序列都要进行求解,因为第
大的数显然只会在其中一个子序列中出现,这也是我们为什么在引入中说,相对于快速排序,快速选择算法可以优化时间复杂度的原因!
性质
时间复杂度
快速选择算法的时间复杂度为。
Q:为什么快速选择算法的时间复杂度为
呢?
A:每次期望寻找的区间长度都会减少一半,则总的期望遍历次数为
。
代码
下面给出快速选择算法的实现代码:
void quick_sort(int q[],int l,int r,int k){
if(l>=r)
return;
int i=l-1,j=r+1,x=q[l+r>>1];
while(i<j){
while(q[i]<x)
i++;
while(q[j]>x)
j--;
if(i<j)
swap(q[i],q[j]);
}
if(k<=j) return quick_sort(q,l,j,k);
else return quick_sort(q,j+1,r,k);
}
上一篇-快速排序的实现 C++算法基础专栏文章 下一篇-归并排序的实现
每周六更新一篇文章,内容一般是自己总结的经验或是在其他网站上整理的优质内容
点个赞,关注一下呗~