前言
这一篇文章就上上一篇博文算法的进一步优化了!
这里我们就利用中位数来进行线性时间的选择算法!
中位数就是指将数据按大小顺序排列起来,形成一个数列,居于数列中间位置的那个数据就是中位数。
算法思路
(1)将输入的n个数划分成
(2)用任意的排序方法对他们进行排序,并取出一共
(3)找出该
(4)将全部的数划分为两个部分,小于基准的在左边,大于等于基准的放右边。
我们用小圆点表示元素,得到如下图:
说明:
图中中间白色圈表示各组数据的中位数,最中间灰色表示中位数的中位数! 箭头是从较小的数指向较大的数!
故我们可以使用该数作为划分的基准(比上一个随机基准的方法会好很多)!
图中
当n≥75时,3A1大于等于
代码描述
int Select(int a[],int p,int r,int k)
{
if(r-p<75)
{
//这里对数组 a[p->r] 进行排序
return a[p+k-1];
}
//(r-p-4)/5相当于n-5
for(int i=0; i<=(r-p-4)/5; i++)
{
//这里将元素每5个分成一组,分别排序,并将该组中位数与a[p+i]交换位置
//使所有中位数都排列在数组最左侧,以便进一步查找中位数的中位数
}
int x = Select(a,p,p+(r-p-4)/5,(r-p-4)/10); //找中位数的中位数
int i = Partition(a,p,r,x); //以x为基准对数组a进行划分
int j = i-p+1;
if(k<=j)
{
return Select(a,p,i,k);
}
else
{
return Select(a,i+1,r,k-j);
}
}