//选择问题
//随机选择主元
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
using namespace std;
const int inf=0x7f7f7f7f;
const int maxn=1000;
int n;
int a[maxn];

int partition(int left,int right)
{//快速排序的一次划分,就可将该主元到达对应位置。
int i=left,j=right+1;
do
{
do i++;while(a[i]<a[left]);
do j--;while(a[j]>a[left]);
if(i<j)
{
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}while(i<j);
int tmp=a[left];
a[left]=a[j];
a[j]=tmp;
return j;
}


void select(int &x,int k)
{
if(n<=0||k>n||k<=0) return;
int left=0,right=n;
do{
int j=rand()%(right-left+1)+left;

int tmp=a[left];
a[left]=a[j];
a[j]=tmp;

j=partition(left,right);

//cout<<a[j]<<endl;
if(k==j+1) {x=a[j];return;}
else if(k>j+1) left=j+1;
else right=j;
}while(true);

}

int main()
{
int k;
while(scanf("%d",&n)!=EOF&&n)
{
memset(a,inf,sizeof(a));
scanf("%d",&k);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int ans;
select(ans,k);
printf("%d\n",ans);
}
return 0;
}

最坏情况的时间复杂度:O(n^2),平均复杂度是线性O(n).

还有二次取中法。大意:将n个数分为k组,对每组找出其中间值放在最前面,然后将每组的中间值 进行比较得到,主元,然后进行划分。