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

计算中值和选择问题
  作者: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;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值