//6.52 设计一个分治算法,在一个具有n个数的数组中找出第二个最大的元素.给出你的算法时间复杂度.
#include<iostream>
using namespace std;
#define Max 30
#define debug 0
//快速排序,按降序排序...
void Qsort(int* A,int low,int high)
{
int temp;
int i=low,j=high;
if(low<high)
{
temp=A[i];
while(i!=j)
{
while(j>i && A[j]<temp) j--;
if(i<j)
{
A[i]=A[j];
i++;
}
while(i<j && A[i]>temp) i++;
if(i<j)
{
A[j]=A[i];
j--;
}
A[i]=temp;
Qsort(A,low,i-1);
Qsort(A,i+1,high);
}
}
}
//debug
void print(int *A)
{
int n=A[0]; //数组元素个数
cout<<"[] = ";
for(int i=1;i<=n;i++) cout<<A[i]<<" ";
cout<<endl;
}
int SearchMaxk(int *A,int low,int high,int k)
//low,high分别为数组元素的上下标,n为数组大小
//返回第k大的元素
{
int p=high-low+1;
//元素小于阈值,则排序后直接返回
if(p<6)
{
Qsort(A,low,high);
return A[k];
}
//将A分成q组,每组5个元素,排除余下的元素.
int q=p/5;
if(debug) cout<<"组数q="<<q<<endl;
//将q组中的每一组单独排序,找出中项,所有中项的集合为M
int M[q+1],i,mi=0;
int l,h;
for(i=1;i<=q;i++){
l=5*i-4; h=5*i;
Qsort(A,l,h);
M[++mi]=A[(l+h)/2]; //取中项入M
}
M[0]=mi;
if(debug){
cout<<"A:";print(A);
cout<<"M:";print(M);
}
//取中项集合M的中项入mm
int q2; // q/2上取整
if(q==1) q2=1;
else q2=q/2;
int mm=SearchMaxk(M,1,q,q2);
if(debug) cout<<"mm="<<mm<<endl;
//将A[low ... high]分成三组,A1[]={a|a>mm} A2=mm A3={a|a<mm}
int A1[Max],A2,A3[Max];
int a1,a3;
A2=mm;
for(a1=0,a3=0,i=low;i<=high;i++){
if(A[i]>mm) A1[++a1]=A[i];
if(A[i]<mm) A3[++a3]=A[i];
}
A1[0]=a1;A3[0]=a3;
if(debug){
cout<<"A1:"; print(A1);
cout<<"A2:"<<A2<<endl;
cout<<"A3:"; print(A3);
system("pause");
}
if(a1>=k) return SearchMaxk(A1,1,a1,k);
if((a1+1)==k) return mm;
if((a1+1)<k) return SearchMaxk(A3,1,a3,k-a1-1);
}
int main()
{
//test
//10:4 5 12 31 6 21 11 15 8 14
//25:8 33 17 51 57 49 35 11 25 37 14 3 2 13 52 12 6 29 32 54 5 16 22 23 7
//输入数组
int A[Max]; /*0号单元保存数组大小*/
cout<<"输入元素个数n:";
cin>>A[0];
cout<<"输入"<<A[0]<<"个元素:";
for(int i=1;i<=A[0];i++){
cin>>A[i];
}
//查找第二大元素
int n=A[0];
cout<<"第二大的元素为:"<<SearchMaxk(A,1,n,2)<<endl;
system("pause");
return 0;
}