一般选择问题也就是从一个数组中随机选出一个第i小的元素,这比一般的找到最小值和最大值也就难多了,我们在快速排序的每次为一个元素找到一个合适的位置,就像快速排序中的Partition中所做的那样。
Randomized_Select(A,p,r,i)
-1- if p==r
-2- return A[p];
-3- q←Random_Partition(A,p,r); //处理一个元素,这个元素位于A[q]
-4- k←q-p+1; //A[q]这个元素在[p,r]中排序位置
-5- if k == q
-6- return A[k];
-7- else
-8- if i<k
-9- Randomized_Select(A,p,q-1,i);
-10- else
-11- Randomized_Select(A,q+1,r,i-k);
改写成一个迭代的过程
Randomized_Select(A,p,r,i)
-0- beg = p; end = r; x =i;
-1- for j←0 to p-r+1
-2- q←Random_Partition(A,beg,end);
-3- k = q-r+1;
-4- if k== x
-5- return A[q];
-6- else
-7- if k>x
-8- end = q-1;
-9- else
-10- beg = q+1;
-11- x = i-k;
#include<iostream>
#include<cstdlib>
using std::rand;
using std::cout;
using std::endl;
void Exchange(int * a, int p, int q)
{
if(p ==q)
return;
else
{
*(a+p) = *(a+p)^*(a+q);
*(a+q) = *(a+p)^*(a+q);
*(a+p) = *(a+p)^*(a+q);
}
}
int Partition(int *a,int p,int r)
{
if(p >= r)
return p;
int x = *(a+r);
int i = p-1;
int j = p;
for(; j<r;j++)
if(*(a+j)<=x)
{
i++;
Exchange(a,i,j);
}
Exchange(a,i+1,r);
return i+1;
}
int rand_(int left, int right)
{
if(left>right)
{
cout<<"There must be something wrong with the number!!!"<<left<<" "<<right<<endl;
return -1;
}
else
{
int x = rand()%(right-left+1);
return left+x;
}
}
int Random_Partition(int *a,int p,int r)
{
int x = rand_(p,r);
Exchange(a,x,r);
return Partition(a,p,r);
}
int Randomize_Select(int *a ,int p, int r, int i)
{
int q = Random_Partition(a,p,r);
int k = q-p+1;
if(k == i)
return *(a+q);
else
if(k>i)
return Randomize_Select(a,p,q-1,i);
else
return Randomize_Select(a,q+1,r,i-k);
}
int main()
{
int a[] = {4,2,6,7,9};
cout<<Randomize_Select(a,0,4,3)<<endl;
}