说明
random文件里面含有一系列正整数。要求选择其中最大的k(k=10)个数,并显示。
目的
考察top-K选择算法的效率,本次将k设置为10。
程序流程
1、读文件到内存数组A;
2、记录程序开始时间;
3、循环1百次
4、 执行top-K选择算法;
(要求不能改变数组A中的内容,对数组A只能读,不能写)
5、循环1百次结束
6、记录程序结束时间;
7、显示1百万次循环的执行时间;
8、显示选择的top-K个数。
9、程序编完之后,理论上分析一下算法的时间复杂性。
(解决方法的实现代码可能还存在着问题,但思路是正确的。)
第一种
对n个数由大到小排序,然后选择前k个最大的数。
排序算法有很多种,快速排序应该综合看来是最优,本代码使用最简单但也是最慢的排序算法来解决,时间复杂度为o(k*n^2)。
c语言实现如下
#include
#include
int Read();
int i=0,a[100000];
int main(){
clock_t start,end;
start=clock();
float runtime;
int j=0,k=0;
Read();
for(int n=0;n<10000;n++){
while(a[j]){
k=j;
while(a[k]){
if(a[j]<=a[k]){
int x=0;
x=a[j];
a[j]=a[k];
a[k]=x;
}
k++;
}
k=0;
j++;
}
printf("第%d次Top-10=",n+1);
for(j=0;j<10;j++){
printf("%d ",a[j]);
}
printf("\n");
j=0;
}
end=clock();
runtime=(double)(end-start);
printf("程序运行时间为%f毫秒(ms)\n",runtime);
return 0;
}
int Read(){
FILE *data;
data=fopen("random.txt","r");
while(fscanf(data,"%d",&a[i])!=EOF){
i++;
}
fclose(data);
}
第二种
(1)扫描数组A, 选择最大的数,并做标记;
(2) 扫描数组A, 选择第二大的数,并做标记;
……
(k) 扫描数组A, 选择第K大的数,并做标记;
代码仍存在问题未能解决,在于每次将数组中的最大值置1后,无法恢复,如果每次使用Read()函数重读只能运行十次,整体来看时间复杂度为o(kn)。
c语言实现如下
#include
#include
#include
int Read();
int i=0,a[100000];
int main(){
clock_t start,end;
start=clock();
float runtime;
int j=0,num=0,max=0,k=0,b[10]={0};
Read();
for(int n=0;n<10;n++){
for(j=0;j<10;j++){
max=0,k=0;
while(a[k]){
if(a[k]>max){
max=a[k];
num=k;
}
k++;
}
b[j]=max;
a[num]=1;
}
printf("第%d次Top-10=",n+1);
for(j=0;j<10;j++){
printf("%d ",b[j]);
}
printf("\n");
}
end=clock();
runtime=(double)(end-start);
printf("程序运行时间为%f毫秒(ms)\n",runtime);
return 0;
}
int Read(){
FILE *data;
data=fopen("random.txt","r");
while(fscanf(data,"%d",&a[i])!=EOF){
i++;
}
fclose(data);
}
第三种
把数组的前k个数先放入优先级队列(底层实现是小根堆,STL模板库有现成的库函数), 从第k+1个数开始扫描。
(1) 如果当前数比优先级队列的队列头(小根堆的堆顶)大,说明当前数需要放入优先级队列,这时先弹出优先级队列的队列头,然后将当前数插入优先级队列。
(2) 如果当前数比优先级队列的队列头(小根堆的堆顶)小,说明当前数不会是top-k中的数,直接滤过,处理下一个数。
在放入优先级队列比较时,小根堆是最优的比较方法,时间复杂度仅为堆的高度h=log(2)k(即以2为底k的对数),总体时间复杂度再乘以外界的n,即o(n*log(2)k)。
本代码使用队列内逐个比较方法,所以时间复杂度为o(kn)。
c语言实现如下
#include
#include
#include
int Read();
int i=0,a[1000000];
int main(){
clock_t start,end;
start=clock();
float runtime;
int h[10]={0};
int k=0,x=0,j=0;
Read();
for(int n=0;n<1000000;n++){
j=0;
while(a[j]){
if(a[j]>h[0]){
h[0]=a[j];
for(k=0;k<9;k++){
if(h[k]>h[k+1]){
x=h[k];
h[k]=h[k+1];
h[k+1]=x;
}
}
}
j++;
}
printf("第%d次Top-10=",n+1);
for(k=9;k>=0;k--){
printf("%d ",h[k]);
h[k]=0;
}
printf("\n");
}
end=clock();
runtime=(double)(end-start);
printf("程序运行时间为%f毫秒(ms)\n",runtime);
return 0;
}
int Read(){
FILE *data;
data=fopen("random.txt","r");
while(fscanf(data,"%d",&a[i])!=EOF){
i++;
}
fclose(data);
}
#include
clock_t start,end;
start=clock();
float runtime;
end=clock();
runtime=(double)(end-start);
printf("程序运行时间为%f毫秒(ms)\n",runtime);
int i=0,a[1000000];
int Read(){
FILE *data;
data=fopen("random.txt","r");
while(fscanf(data,"%d",&a[i])!=EOF){
i++;
}
fclose(data);
}