快速排序的基本思想:
(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;
}