好久没写代码了,练练手。从其他地方看的,其实思想跟快排一样,不过只是找第K个元素,所以不用全部都排序。
复杂度号称是O(N),不过算上交换,我觉得实际上是比O(要大的)。交换代价应该比比较要大。
#include <iostream>
using namespace std;
int count_cmp = 0;
int count_swp = 0;
void swap(int &a,int &b)
{
int tmp=a;
a=b;
b=tmp;
}
int partition(int a[],int from ,int to){
int i=from-1;
int r=to;
for(int j=i+1;j<r;j++)
{
if(a[j]<a[r])//找到小于a[r]的元素
{
count_cmp++;
//将a[j]与第一个大于a[r]的a[i]互换
if (i + 1 != j)
{
count_swp++;
swap(a[++i],a[j]);
} else {
cout <<"no need to swap!"<<endl;
}
}
}
swap(a[++i],a[r]);//最后将a[r]与当前大于a[r]的最左边元素互换
return i;
}
int RandomSelect(int a[],int from ,int to,int index)
{
if(from == to) return a[from];//如果只有一个元素,直接返回该元素
int k = partition(a,from,to);//获取分隔元素,与快排相同
cout<<k<<endl;
int len = k-from+1;
if(len == index) return a[k]; //如果index正好是k,说明,该分隔值就是第index个元素
else if (len > index)//如果长度大于index,说明第index个元素在k左边
return RandomSelect(a,from,k-1,index);
else//否则在右边(迭代时需要调整index值)
return RandomSelect(a,k+1,to,index-len);
}
int main(){
int a[]={0,1,9,4,8,5,6,3,2,7};
int index = 5;
int val=RandomSelect(a,0,8,index);
cout<<"index = "<<index<<"\tval = "<<val<<endl;
cout<<count_cmp<<"\t"<<count_swp<<endl;
return 0;
}