数组中找出第二个最大的元素(第k大的元素)

本文介绍了一种分治算法,用于在数组中高效地找到第二大元素。该算法通过快速排序和递归技术实现,能够在较短时间内完成任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//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;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值