掌握顺序统计算法的设计思想;
实验内容
给定数组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]];
}