当n比较小时,隐含的常数较大
#include<iostream>
#include<algorithm>
using namespace std;
int PARTITION(int a[], int l ,int r,int k)//k为分界值下标
{
swap(a[r],a[k]); //把分界值交换到右边
int left = l,right = r,pivot = a[r];
while(left<right)
{
swap(a[left],a[right]);
while(right>left&&a[right]>pivot)right--;
while(left<right&&a[left]<=pivot)left++;
}
swap(a[right],a[l]);
return left;
}
void insertsort (int a[],int l, int r)//插入排序非递归
{
int key,i;
for(int j=l+1;j<=r;j++)
{
key=a[j];
for(i=j-1;i>=l&&a[i]>key;i--)
{
a[i+1]=a[i];
}
a[i+1]=key;
}
}
int findmid(int a[],int l, int r)
{
if(r-l+1 <= 5){
insertsort(a,l,r);
return (l+r)/2;
} //当元素小于等于5 排序并返回分界值下标
int k=l,mid;
int y = (r-l+1)%5;
for(int i = l;i+4<=r;i+=5)
{
insertsort(a,i,i+4);
swap(a[k],a[i+2]);
k++;
}
if(y){
insertsort(a,r-y+1,r);
swap(a[k],a[r-y/2]);
k++;
}
return findmid(a,l,l+k-1);
}
int select(int a[],int l,int r,int i)
{
int pivot = findmid(a,l,r);//存储分界值的下标
int m = PARTITION(a,l,r,pivot);
int k = m-l+1;
if(i == k){
return a[m];
}else if(k>i){
return select(a,l,m-1,i);
}else return select(a,m+1,r,i-k);
}
int main()
{
int a[11] = {11,233,13,3,3,22,65464,-1,-43,21221,4};
for(int i = 1;i<=11;i++)
printf("%d ",select(a,0,10,i));
printf("\n");
insertsort(a,0,10);
for(int i = 0;i<11;i++)
printf("%d ",a[i]);
}