递归与分治策略之利用中位数线性时间选择

来源:互联网 发布:淘宝客推广海报 编辑:程序博客网 时间:2024/05/22 13:51

前言

这一篇文章就上上一篇博文算法的进一步优化了!
这里我们就利用中位数来进行线性时间的选择算法!

中位数就是指将数据按大小顺序排列起来,形成一个数列,居于数列中间位置的那个数据就是中位数。

算法思路

(1)将输入的n个数划分成 n5 个组,当然最后一组的数目可能是小于5的!
(2)用任意的排序方法对他们进行排序,并取出一共 n5 个中位数。
(3)找出该 n5 个中位数中的中位数。(如果 n5 是偶数则取相对大的那个数)
(4)将全部的数划分为两个部分,小于基准的在左边,大于等于基准的放右边。

我们用小圆点表示元素,得到如下图:
选择划分基准

说明:
图中中间白色圈表示各组数据的中位数,最中间灰色表示中位数的中位数! 箭头是从较小的数指向较大的数!

故我们可以使用该数作为划分的基准(比上一个随机基准的方法会好很多)!

比基准小的数

图中

3A1=3(n5)10

当n≥75时,3A1大于等于14n。所以按此基准划分所得的左右2个子数组的长度都至少缩短14

代码描述

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);      }  }  
原创粉丝点击