BFPTR算法(中位数的中位数算法)求n个数中第k大的数

        BFPTR算法求n个数中第k大(即第n-1-k小)的数,其思想是基于快速排序中对Partion的pivot值进行优化,快速排序中每一趟快排的pivot的选取一般是数组的首项或者尾项(数值比较随机),而BFPTR是每次选择5分中位数的中位数作为pivot进行下一趟快速排序的,这样做可以使算法的时间复杂度由最坏的O(n^2)变为O(n).

实现代码如下:

#include <iostream>
using namespace std;
const int maxn=1000;
int a[maxn],n,k; //求有n个元素的数组a中第k大(第n-1-k小)的数
void Insert_Sort(int a[],int l,int r)
{//由于只有5个数,插入排序即可
    for(int i=l;i<=r;i++)
    {
        int tmp=a[i],j=i-1;
        for(;j>=l&&tmp<a[j];j--) a[j+1]=a[j];
        a[j+1]=tmp;
    }
}
int Find_mid(int a[],int l,int r)
{//寻找中位数的中位数
    if(l==r) return a[l];
    int i=0,n=0;
    for(int i=l;i<r-5;i+=5)
    {
        Insert_Sort(a,i,i+4); //每5个数按升序排列
        n=i-l;
        swap(a[l+n/5],a[i+2]); //将找到的中位数放在数组a的前面
    }
    //处理剩余元素
    int res=r-i+1;
    if(res>0)
    {
        Insert_Sort(a,i,i+res-1);
        n=i-l;
        swap(a[l+n/5],a[i+res/2]);
    }
    n/=5; //a[0..n]存放本趟分组的中位数
    if(n<=1) return a[l]; //当中位数小于2个(下标n<=1)时直接返回较小的
    return Find_mid(a,l,l+n); //大于2个时递归继续寻找中位数
}
int Find_pos(int a[],int l,int r,int mid)
{//找到中位数的中位数在a中的下标
    for(int i=l;i<=r;i++)
        if(a[i]==mid) return i;
    return -1;
}
int Partion(int a[],int l,int r,int pos)
{//进行划分过程
    swap(a[pos],a[l]); //将找到的中位数的中位数(即mid)换到数组a的最前面
    int i=l,j=r;
    int pivot=a[l];
    while(i<j)
    {
        while(i<j&&a[j]>=pivot) j--;
        a[i]=a[j];
        while(i<j&&a[i]<=pivot) i++;
        a[j]=a[i];
    }
    a[i]=pivot;
    return i; //返回pivot(即mid值)的下标
}
int BFPTR(int a[],int l,int r,int k)
{
    int mid=Find_mid(a,l,r); //寻找中位数的中位数
    int pos=Find_pos(a,l,r,mid); //找到中位数的中位数在a中的下标
    int i=Partion(a,l,r,pos);
    int m=i-l+1; //m即为mid归位后在a中的位置
    if(m==k) return a[i];
    if(m>k) return BFPTR(a,l,i-1,k);
    return BFPTR(a,i+1,r,k-m);
}
int main()
{
    while(cin>>n)
    {
        for(int i=0;i<n;i++) cin>>a[i];
        cin>>k;
        cout<<"The "<<k<<" number in the array is:"<<BFPTR(a,0,n-1,k)<<endl;
        for(int i=0;i<n;i++) cout<<a[i]<<" ";
        cout<<endl;
    }
    return 0;
}
/*
输入:
10
2 1 3 9 8 0 5 6 4 7
5
输出:
The 5 number in the array is:4
0 1 3 2 4 5 6 7 8 9
*/






你可能感兴趣的:(BFPTR算法(中位数的中位数算法)求n个数中第k大的数)