线性时间选择

时间:2021-11-09 17:17:43

参考算法设计与分析。

#include <bits/stdc++.h>

using namespace std;

inline int Random(int x,int y)
{
    int ran=rand()%(y-x)+x;
    return ran;
}

int Partition(int a[],int p,int r,int k)
{
    int i=p-1;
    int j=r+1;
    while(true)
    {
        while(a[++i]<k&&i<r);
        while(a[--j]>k);
        if(i>=j)
            break;
        swap(a[i],a[j]);
    }
    return j;
    //返回i跟返回j是一样的。
}

int Select(int a[],int p,int r,int k)
{
    if(r-p<=75)
    {
        sort(a+p,a+r+1);
        return a[k+p-1];
    }
    //(r-p-4)相当于n-5;
    //将元素5个分为一组,分别排序,并将该数组的中位数与a[p+i]交换位置
    //将所有中位数都排在数组最左侧,以便进一步查找中位数的中位数.
    for(int i=0;i<=(r-p-4)/5;i++)
    {
        sort(a+p+i*5,a+p+i*5+5);
        swap(a[p+i],a[p+i*5+2]);
    }
    int x=Select(a,p,p+(r-p-4)/5,(r-p-4)/10);//找中位数的中位数。
    int i=Partition(a,p,r,x);//找寻中位数的位置;
    int j=i-p+1;            //记得这块得改变k在数组中的位置。
    if(i>k)
        Select(a,p,i,k);
    else
        Select(a,i+1,r,k-j);//记得这块得改变k在数组中的位置
}

int main()
{
    int a[100];
    srand((unsigned)time(0));
    for(int i=0;i<100;i++)
        a[i]=Random(0,500);
    cout<<endl;
    printf("第83小元素是%d\n",Select(a,0,99,83));
    //重新排序,比较结果。
    sort(a,a+100);
    printf("a[82]=%d\n",a[82]);
    return 0;
}