/*
选择问题是求一个n个数列表的第k个最小元素的问题.
算法:把一个数组的元素分成两个子集:如果值P是两个分区的中轴,那么一个子集包含小于等于P的
元素,另一个子集包含那些大于等于P的元素.
先假设S是分区的分割位置.如果S=K,中轴P就是选择问题的解;如果S>K,整个列表的第K个最小元素
就是分区数组的左边部分的第K个最小元素;如果S<K,找数组右边部分的第K-S个最小元素.
*/
#include<stdio.h>
int Partition(int a[],int l,int r)
{
int p,i,j,temp;
p=a[l];
i=l;
j=r+1;
do {
do {
i++;
}while(a[i]<p); /*从左到右找第一个大于等于中枢的值*/
do {
j--;
}while(a[j]>p); /*从右到左找第一个小于等于中枢的值*/
temp=a[i];
a[i]=a[j]; /*交换这两个的值*/
a[j]=temp;
}while(i<j);
temp=a[i]; /*当 i>=j时,撤消最后一次交换*/
a[i]=a[j];
a[j]=temp;
temp=a[l];
a[l]=a[j];
a[j]=temp;
return j;
}
int main()
{
int a[100],n,k,s,i,l,r;
printf("Please enter the len of the array:");
scanf("%d",&n);
printf("Please enter the array:");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("Please enter the number of k:");
scanf("%d",&k);
k--;
l=0;
r=n-1;
do {
s=Partition(a,l,r);
if(s>k)
r=s-1;
if(s<k)
l=s+1;
}while(s!=k); /*一直做到S=K为止*/
printf("The %dth min number is: %d./n",k,a[k]);
return 0;
}