1、如果n个数是不重复的,可以先找出第m大的数,再遍历整个数组,小于等于m的数就是目标元素。实现及测试代码如下所示:
#include<iostream>
using namespace std;
#include<sys/time.h>
#include<stdlib.h>
#define N 100000000
#define N_min 100
#define random(i) (rand()%i)
int a[N];
int flag[N];
//找到第k小的元素
int find_k_min(int *a,int n,int k)
{
if(a==NULL||n<1||k<1||k>n)
return -1;
int i=0;
int j=n-1;
int x=a[i];
while(i<j)
{
for(;i<j;j--)
{
if(a[j]<x)
{
a[i++]=a[j];
break;
}
}
for(;i<j;i++)
{
if(a[i]>x)
{
a[j--]=a[i];
break;
}
}
}
if(i==k-1)
return x;
else if(i>k-1)
return find_k_min(a,i,k);
else
return find_k_min(a+i+1,n-i-1,k-i-1);
}
int main()
{
int num=0;
struct timeval tv;
while(num<N) //生成含N个不重复元素的随机数组
{
int buf=random(N);
if(flag[buf]==0)
{
flag[buf]=1;
a[num++]=buf;
}
}
gettimeofday(&tv,NULL); //开始时刻
cout<<"start:"<<tv.tv_sec<<','<<tv.tv_usec<<endl;
int k=find_k_min(a,N,N_min);
for(int i=0;i<N;i++)
{
if(a[i]<=k)
cout<<a[i]<<' ';
}
cout<<endl;
gettimeofday(&tv,NULL); //结束时刻
cout<<"end:"<<tv.tv_sec<<','<<tv.tv_usec<<endl;
return 0;
}
2、如果可能有重复的数,可以前m个元素建立一个最大堆,剩下的元素依次与堆顶元素比较,如果小于堆顶元素就替换之,然后调整堆,最后的堆即为最小的m个元素,实现及测试代码如下所示:
#include<iostream>
using namespace std;
#include<stdlib.h>
#include<sys/time.h>
#define N 100000000
#define N_min 100
#define random(i) (rand()%i)
int a[N];
int flag[N];
//堆调整函数
void heap(int *a,int n,int i)
{
int child;
int tmp=a[i];
for(;2*i+1<n;i=child)
{
child=2*i+1;
if(child+1<n&&a[child]<a[child+1])
child++;
if(tmp<a[child])
a[i]=a[child];
else
break;
}
a[i]=tmp;
}
//获得num个元素中最小的n个元素
void get_min_n(int *a,int num,int *min,int n)
{
if(a==NULL||min==NULL||num<=1||n<1||n>num)
return;
for(int i=0;i<n;i++)
min[i]=a[i];
for(int i=n/2-1;i>=0;i--)
heap(min,n,i);
for(int i=n;i<num;i++)
{
if(a[i]<min[0])
{
min[0]=a[i];
heap(min,n,0);
}
}
}
int main()
{
int num=0;
struct timeval tv;
while(num<N) //生成含N个不重复元素的随机数组
{
int buf=random(N);
if(flag[buf]==0)
{
flag[buf]=1;
a[num++]=buf;
}
}
int *min=new int[N_min];
gettimeofday(&tv,NULL); //开始时刻
cout<<"start:"<<tv.tv_sec<<','<<tv.tv_usec<<endl;
get_min_n(a,N,min,N_min);
for(int i=0;i<100;i++)
cout<<min[i]<<' ';
cout<<endl;
gettimeofday(&tv,NULL); //结束时刻
cout<<"end:"<<tv.tv_sec<<','<<tv.tv_usec<<endl;
delete[]min;
return 0;
}