问题:给定线性序集中n个元素和一个整数k,1<=k<=n,要求找出这n个元素中第k小的元素。
我们采用快速排序的思想来解决这个问题。首先我们要找到基准的位置,如果基准的位置小于k,则表示第k小的元素在基准的后面,否则在基准的前面。
如果能在线性时间内找到一个划分基准,使得按这个基准所划分出的2个子数组的长度都至少为原数组长度的 ε 倍(0<ε<1是某个常数),那么就可以在最坏情况下用O(n)时间完成选择任务。
算法过程如下:
- 将这个函数定义为select(nums,p,r,k),即为找到nums[p:r]数组中第k(1<=k<=n)小的元素。
- 假如数组的长度小于75,那么直接用快排来解决。
- 将n个输入元素划分成ceil(n/5)个组,每组5个元素,只可能有一个组不是5个元素。用任意一种排序算法,将每组中的元素排好序,并取出每组的中位数,共ceil(n/5)个。
- 递归调用select来找出这ceil(n/5)个元素的中位数。如果ceil(n/5)是偶数,就找它的2个中位数中较大的一个。以这个元素作为划分基准。
//一次快排
int Partition(int nums[],int p,int r,int x)
{
if(p>r) return -1;
//找出基准x的位置并与第一位交换
for(int i=p;i<=r;i++)
{
if(nums[i]==x)
{
swap(x,nums[p]);
break;
}
}
int left=p,right=r;
while(left<right)
{
while(left<right && nums[right]>=x) right--;
nums[left]=nums[right];
while(left