算法导论复习第九章

/*算法导论第九章,中位数和顺序统计。
9.1 第i个顺序统计的意思是集合中第i个小的元素,对于n个数,当为奇数的时候中位数就是指第(n+1)/2的那个数,当是偶数的时候就是有两个
中位数,包括上中位数(n+1)/2(向上取整),以及(n+1)/2(向下取整),对于n个数中求最大值或者最小值一般情况下的话,需要的是n-1个次比较,
对于求最大也求最小的话,需要比较的次数是2(n-1)次;但是也有一种方法把比较的次数减少到3*(n/2)(向下取整),具体方法是:首先是一对数进行对比
求出数中最大和最小的数字,之后对余下的数字,两两进行输入,首先进行相互比较,大的和之前的大的比较,小的和小的比较,那么对于n为奇数以及为偶数相应
就对于最初的最大和最小的数字进行初始化,当为奇数的时候就是第一个赋值为最大以及最小,为偶数的时候就首两个进行赋值,如此进行计算的话,奇数的时候进行
比较的次数是3*n/2(向上取整),当为偶数的时候比较次数就是:3*(n-2)/2+1(向上取整),具体代码如下
*/
#include <iostream>
#include <algorithm>
using namespace std;
#define length 10
void print(int *A)//打印
{
	int i;
	for (i=0;i<length;++i)
	{
		cout<<A[i]<<" ";
	}
	cout<<endl;
}

/***************最初版本的求最大最小*****************/
pair<int,int> min_max(int *A)
{
	int min=0xfffffff;
	int max=0;
	int i;
	for (i=0;i<length;++i)
	{
		if (min>A[i])
		{
			min=A[i];
		}
		if(max<A[i])
		{
			max=A[i];
		}
	}//比较2次;
	pair<int,int> p(min,max);
	return p;
}

/**************使用新的比较方法(3*n)/2次完成*********************/
pair<int,int>  max_min(int *A)
{
	int max,min,i;
	if((length)%2!=0)
	{
		min=max=A[0];
		i=1;
	}else
	{
		min=A[0];
		max=A[1];
		if(A[0]>=A[1])
		{
			min=A[1];
			max=A[0];
		}
		i=2;
	}
	for (;i<length;i+=2)
	{
		if(A[i]>=A[i+1])
		{
			if(A[i]>max)
			{
				max=A[i];
			}
			if(A[i+1]<min)
			{
				min=A[i+1];
			}
		}else
		{
			if(A[i]<min)
			{
				min=A[i];
			}
			if(A[i+1]>max)
			{
				max=A[i+1];
			}
		}
	}
	/*
	参考师姐的做法:缩减代码数;学习下;搞ACM的果然不是盖的。
	for(i;i<length;i+=2)
	{
		int a=min(A[i],A[i+1]);
		int b=A[i]+A[i+1]-a;
		if(a<min)
		{
			min=a;
		}
		if(b>max)
		{
			max=b;
		}
	}
	*/
		pair<int,int> p(max,min);
		return p;
}

/*****************期望线性时间选择******************************/
//选择第i小的,书上说,一般情况下选择问题比最小值问题复杂,但是这里给出的方法就是一种可以在线性时间内解决选择最小的;
int partion(int * A,int p,int r)
{
	int x=A[r];
	int i=p-1;
	for (int j=p;j<r;++j)
	{
		if(A[j]<=x)
		{
			swap(A[++i],A[j]);
		}
	}
	swap(A[i+1],A[r]);
	return i+1;
}

int rand_partion(int *A,int p,int r)
{
	int i=rand()%(r-p+1)+p;
	swap(A[r],A[i]);
	return partion(A,p,r);
}

int randselect(int * A,int p,int r,int i)
{
	if(p==r)
		return A[p];
	int q=rand_partion(A,p,r);
	int k=q-p+1;
	if(k==i)//第i个
		return A[q];
	else 
		if(i<k)
			return randselect(A,p,q-1,i);//如果第i个数比k小
		else 
			return randselect(A,q+1,r,i-k);
}

int main()
{
	int num;
	int A[length];
	int pos;
	for (num=0;num<length;++num)
	{
		cin>>A[num];
	}
	print(A);
	cout<<min_max(A).first<<" "<<min_max(A).second<<endl;
	cout<<"----------------"<<endl;
	cout<<max_min(A).first<<" "<<max_min(A).second<<endl;
	cout<<"----------------"<<endl;
	cin>>pos;
	cout<<randselect(A,0,length-1,pos)<<endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值