要求:给定一个数组array[n],寻找大小排在第k的元素
思路一:最直接的思路就是先排序,这样可以直接通过数组下标找到第k大的元素,最好的快速排序时间复杂度为O(nlogn)。
思路二:我们可以在快速排序的基础上进行改进,即运用快速排序框架,不过快速排序中的基准元素,我们采用随机划分而不是快速排序那样指定为一个固定的值。此方法时间复杂度为O(n)
此思路的代码如下:
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<time.h>
using namespace std;
int random(int p,int r)
{
return (rand()%(r-p+1)+p); }
int partion(float a[],int p,int r)
{
int x = a[r];
int i=p-1;
for(int j = p;j<r;++j){
if(a[j]<=x){
++i;
swap(a[i],a[j]);
}
}
swap(a[i+1],a[r]);
return i+1;
}
int part(float a[],int p,int r)
{
int i=random(p,r);
swap(a[i],a[p]);
return partion(a,p,r);
}//该算法的主体框架为快速排序的框架,但与快速排序不同的是,快速排序是通过递归框架
//对数组进行排序,但此算法通过递归框架只对数组中的第k元进行筛选,所以递归的出口不同
//快速排序中的递归出口为if(high>low),但该函数的递归出口为if(k-1==i-p)
//与快速排序相同的是都存在一个划分过程
//如果单是求第k元的话,该函数的参数可以简化,即p=0,这样j==i
float select(float a[],int p,int r,int k)
{//在数组a中从下标p到r中求第k小的元素
if(p==r)
{
return a[p];
}
int i=part(a,p,r);//对数组a随机划分
int j=i-p;//+1;//此处之所以要i-p因为该函数从数组p下标开始,而不一定从0开始
if(k-1==j)//因为数组下标从0开始,所以第k小元素下标为k-1
return a[i];//递归出口,返回该元素
else if(k-1<j)
return select(a,p,i-1,k);
else
return select(a,i+1,r,k-j-1); }
void bubble(float a[], int n)
{
int i,flag=1;
for(i=1;i<=n-1&&flag;i++)
{
flag=0;
for(int j=0;j<n-i;j++)
{
if(a[j+1]<a[j])
{
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
flag=1; } }
}
}
int main()
{
int n,t,i,j=0;
cout<<"请输入元素的个数n"<<endl;
cin>>n;
// float *p=(float *)malloc(n*sizeof(float));
float *p=new float[n];
cout<<"请输入每个元素的值"<<endl;
for(i=0;i<n;i++)
{
cin>>p[i];
}
cout<<"请输入要寻找第k元的k值"<<endl;
int k;
cin>>k;
cout<<select(p,0,n-1,k)<<endl;
return 1;
}
程序运行结果如下: