您的位置:首页 > 其它

计算中值和选择问题,如何快速

2015-04-15 23:33 330 查看
计算中值和选择问题
作者:Keifer Gu
算法来源:算法设计与分析基础(美)Anany Levitin

一、如何快速获得一个数列的第K大的元素

第我门的第一反应一般是应该先将这个数列进行排序,然后找出数列中的第K个最小的数,但是这样做太浪费效率。基于减治法的思想,我们这里有一个高效的算法。

二、算法思想
首先对寻找中值的情况进行分析:

中值的左边全部比这个数小,右边则全部比它大,由此也可知,我们根本不需要给这个数列进行排序,只需要寻找到这个数即可。
给出下面这组数:
1 10 9 7 12 8 2 15


这里一共有九个数,那么中值就是第五个最小的数。
我们以第一个数4为基准,将这个数列排列为4的左边均比4小,右边均比4大的数列。
具体代码的实现过程我们后面来看,第一次排列后的结果为:
2 1 9 7 12 8 10 15
现在数字4到了第三位,我们可以看到4它的前面的数都比它小,后面的数都比它大,可以得知,数字4是这个数列中第三小的数,因为我们要找的中位数是第五小的数,也就是说在4前面的数只可能第一小,第二小,那么前面的数我们都可以不看了,只看后面的。
现在对后面的数进行处理:
9 7 12 8 10 15
同样的,以第一个数为基准,处理后结果为:
8 7 9 12 10 15

而9是第六小的数,因为删除了前三小的数,就在这里是第三,在整个数列中就是第六。
六大于五,那么我们要找的数就在它的前面了:
8 7
以8为基准,处理后为:
7 8
现在的8就是第五小的数了,及我们需要的中值。

三、代码实现

#include <iostream>
using namespace std;

int ValSelect(int a[],int l,int r,int k)  //l为需要处理的数组起点,r为终点,k为需要找到的第几小的值
{
int i=l,j=r;     //i 是起点,最前面的数,j 是最后面的数
while(i<j&&a[j]>=a[i])    //寻找到比a[i]大的 最小的j
j--;                  //j从最后一个向前循环,找到比a[i]小的数
if(i<j)                   //此时则将比a[i]小的数放到最前面
swap(a[i],a[j]);
while(i<j&&a[i]<=a[j])    //此时是让i从前面往后递增,直到找到比a[j]小的数,注意此时的a[j]经过了交换,等于前面的a[i]也就是第一个数
i++;
if(i<j)
swap(a[i],a[j]);       //再次交换
if(i<k)
return ValSelect(a,i+1,r,k);   //递归调用,i的值就是现在的数是第几小的数,k就是我们需要的第几小的数
else if(i>k)
return ValSelect(a,l,i-1,k);
else return a[i];          //此处就是i=k,就是找到了我们需要的数,返回该值
}

int main()
{
int a[9]={4,1,10,9,7,12,8,2,15};
int b = ValSelect(a,0,8,4);
cout<<b<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐