给定数组A[0..n-1],试设计一个算法,在最坏情况下用n+logn次比较找出A[0..n-1]中元素的最大值和次大值

掌握顺序统计算法的设计思想;

实验内容

给定数组A[0…n-1],试设计一个算法,在最坏情况下用n+logn次比较找出A[0…n-1]中元素的最大值和次大值。

具体思路
顺序统计算法其实就是锦标赛算法,即两两比较得出两者之中最优, 再将该最优值与其他组的最优值进行比较, 得出最终的最优解。
分析:
例如这n(n=8)个数分别是:8 7 9 2 3 6 10 12
第一轮比赛:(8,7) (9,2) (3,6) (10,12) 比较了4次
得到第一轮的入选者:8 9 6 12
第二轮比赛:(8 9) (6 12) 比较了2次
得到第二轮的入选者:9 12
第三轮比赛:(9 12) 比较了1次
得到第三轮的入选者:12 12既是比赛的冠军
以上得到冠军总共比较了7次,即n-1次
只有和冠军比过的人才有可能是亚军
为什么只有和冠军比过的人才有可能是亚军,因为都没和冠军必过,证明肯定分组不是和冠军一个分组的而且别另外的数给虐了。

代码实现

#include<iostream>
using namespace std;
void search(int *a,int *result,int left,int right)
{
	//如果当前数组的长度小于等于二, 那么直接返回最大值和次大值
	if(left==right)
	{
		result[0]=result[1]=left;
	}
	else if(left==right-1) 
	{
		if(a[left]>a[right])
		{
			result[1]=left;
			result[0]=right;
		}
		else
		{
			result[1]=right;
			result[0]=left;
		}
	}
	else        //如果数组长度大于二
	{
		int m=(right-left+1)/2;          //m是数组中间的数, 将数组以m为分界线分为两部分使用锦标赛思想, 第一个和最后一个相比, 第二个和倒数第二个相比, 以此类推, 将较大的数放到后面去, 较小的数放在前面
		for(int i=left;i<left+m;i++)
		{
			if(a[i]>a[i+m])
			{
				int temp=a[i];
				a[i]=a[i+m];
				a[i+m]=temp;
			}
		}
		search(a,result,left+m,right);       //对后半部分再次一分为二进行锦标赛算法, 这样最终得到的a[result[1]]就是最大值, 但是a[result[0]]不一定
		if(a[result[1]-m]>a[result[0]]) result[0]=result[1]-m;    //在每次求出最大值之后, 此时的次大值仅仅是最后一次和最大值相比的数, a[result[1]-m]则是倒数第二个和最大值相比的数, 因此要在这两个数之间进行选择
	}
}
int main()
{
	int N;
	cin>>N;
	int a[N];
	for(int i=0;i<N;i++)
	{
		cin>>a[i];
	}
	int result[2];                              //result[1]存放的是最大值, result[0]存放的是次大值。
	search(a, result, 0, N-1);
	cout<<a[result[1]]<<endl<<a[result[0]];
}

转载自https://blog.csdn.net/qq_42818329/article/details/90647068

猜你喜欢

转载自blog.csdn.net/weixin_44044395/article/details/109032439
今日推荐