第k小数(快排)

快速排序的基本思想:

(1)分解:以a[p]为基准元素将a[p:r]划为3段a[p:q-1],a[q]和a[q+1:r],使得a[p:q-1]中任何元素小于等于a[q],a[q+1:r]中任何元素大于等于a[q]。下标q在划分过程中确定。

(2)递归求解:通过递归调用快排算法,分别对a[p:q-1]和a[q+1:r]进行排序。

(3)合并:由于a[p:q-1]和a[q+1:r]都已经排好序了,所以不用任何操作。

选取第k小数的基本思想:

我们可以根据返回的下标q去判断,

(1)当k等于q时,当前下标所代表的数就是我们要找的第k小数。(因为q前面的数都比他小,q后面的数都比他大)

(2)当k<q时,对p~q这一部分寻找

(3)当k>q时,对q~r这一部分寻找

#include <iostream>
#include <cstdio>
#include <stack>
#include <cstdlib>
using namespace std;
void swap(int a[],int i,int j)
{
    int t=a[i];
    a[i]=a[j];
    a[j]=t;
}
int partition(int a[],int p,int q)
{
    int x=a[p];
    int i=p;
    for(int j=i+1;j<=q;j++)
    {
        if(a[j]<=x)
        {
            i++;
            swap(a,i,j);
        }
    }
    swap(a,p,i);
    return i;
}
void qSort(int p,int q,int a[])//快排
{
    if(p<q)
    {
        int r=partition(a,p,q);
        qSort(p,r-1,a);
        qSort(r+1,q,a);
    }
}
int Select(int a[],int p,int q,int k)//寻找第k小数
{
    if(p<q)
    {
        int r=partition(a,p,q);
        if(k==r)
            return a[r];
        else if(k<r)
            return Select(a,p,r-1,k);
        else
            return Select(a,r+1,q,k);
    }
    return -1;
}
int main()
{
    int a[100],n,k;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
//        qSort(0,n-1,a);
//        for(int i=0;i<n;i++)
//            printf("%d ",a[i]);
//        printf("\n");
        scanf("%d",&k);
        printf("%d\n",Select(a,1,n,k));
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/huanhuanxiaoxiao/article/details/78321765
今日推荐