实验8 查找算法实验比较
实验目的
基于教材内容,从顺序查找、二分查找、基于BST的查找和哈希中任选两种查找算法,实现并比较性能。
基本要求
(1)对实现的查找算法进行实验比较,在不同数据规模(N)下执行100次成功查找,以表格形式记录最小、最大和平均查找时间;在不同数据规模(N)下执行100次不成功查找,以表格形式记录最小、最大和平均查找时间。
(2)查找算法要基于教材,测试输入的整数数据文件(5个,文件中数据规模N分别是100,1K,10K,100K和1M),每次查找的比较次数和时间也要输出到文件中。
(3)提交最终实验作业。用附件的形式,提交两个文件:一个压缩包(包含源码和5个用于查找测试的数据文件);一个pdf文档(文档中包含实验日志和一个根据基本要求(1)记录实验结果的表格,然后进行适当的实验结果分析)。
实验八-查找算法实验比较-实验日志
【2020.12.26】
任务:复习教材关于二分查找、基于BST的查找和哈希查找的算法,理解算法思想,对算法的实现方式有一个总体的认识。
【2020.12.28】
任务:复习关于文件输入输出流的相关知识,复习关于rand函数的相关知识。构思关于随机数生成的格式。同时查资料了解关于计算查找时间代价的方法,得知了时钟频率LARGE_INTEGER frequency,可以用完成查找后的时钟频率减去之前的时钟频率,得出查找所用的时间。
【2020.12.29】
任务:完成随机生成数的main函数文件,分别生成大小为100,1K,10K,100K,1M大小的数据文件,再生成两个被查找数据的文件,分别包含了100个数据,一个是可以被查找到的100个数据,另一个是无法查找的100个数据,分别命名为“success.text”和“fail.txt”。
遇到问题1:打开文件后忘记关上文件了
出错原因:没有关上文件
修改方式:在一个文件输入结束后,加入close()函数,关闭文件
遇到问题2:
出错原因:上一个文件输入已将用过outfile这个输出了,在这里起了冲突。
修改方式:改成outfile1即可。同时其他文件的输出也要做相应改变。
遇到问题3:编译通过,但允许出错
出错原因:猜测是因为一维数组超空间了
改进方式:改用vector容器储存随机数
修改后运行成功。
五组随机数和两组测试数据生成工作完成。
【2021.1.1】
任务:完成顺序查找、哈希查找的实现,再根据时钟频率,完成每组数据成功和失败的各一百次查找,记录所用时间,制作相应表格。
顺序查找
哈希查找
结果分析:
顺序查找的时间复杂度为O(n),在规模增大时,可以明显看出其查找的平均时间增大.尤其是在查找失败的情况下,因为要将所有值遍历一次,从表格可以看出其平均时间和规模呈正比增长;
哈希查找的时间复杂度为O(1),在规模增大的情况下,可以看出平均时间消耗几乎一样。
可见,在进行查找时,不同的算法在数据量大规模增加时,所需要的时间代价差距十分悬殊,我们在平时的作业、练习中遇到的几乎都是规模很小的数据,这时候采取增长幅度大的算法可能感受不出来,一旦数据量几何式增长,代价大的算法很可能直接造成运行崩溃,所以我们应该对各种算法的时间、空间代价有一个基本的认识,尽量采用代价小的算法。
【2021.1.2】
任务:完善实验日志,上交实验代码和日志报告。
查找代码:
#include <iostream>
#include <time.h>
#include <algorithm>
#include <fstream>
#include <windows.h>
#include <vector>
#define random(a,b) (int)(((double)rand()/RAND_MAX)*pow(10,rand()%7))
using namespace std;
const int maxn=1048576;
int C[maxn+5];//散列函数,取余法
LARGE_INTEGER frequency;//时钟频率
//const int maxn=1e7;//10M
double begin_,_end,dft,dff,dfm;
int main()
{
srand((int)time(NULL));//time seed
QueryPerformanceFrequency(&frequency);//获得时钟频率
dff=(double)frequency.QuadPart;//取得频率
double mint=100000,maxt=0,average=0;
int yes[100],no[100];
ifstream input1("success.txt");
for(int i = 0 ; i < 100; i++)
input1 >> yes[i];
input1.close();
ifstream input2("fail.txt");
for(int i = 0 ; i < 100; i++)
input2 >> no[i];
input2.close();
int n = 1000*10;
cout <<"----------进行顺序查找----------" << endl;
vector<int> num_list;int key;
ifstream input3("10K.txt");
for(int i = 0 ; i < 100; i++)
{
input3 >> key;
num_list.push_back(key);
}
input3.close();
ofstream outfile1("10K_time.txt");
for(int i=0;i<100;i++)
{
int x=yes[i];
int count=0;//查找次数
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值1
for(int j=0;j<n;j++)
{
count++;
if(num_list[j]==x) break;
}
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
cout<<"顺序表查找成功,查找次数为"<<count<<endl;
outfile1<<"顺序表查找成功,查找次数为"<<count<<endl;
mint=min(mint,dft*1000000);//最小时间
maxt=max(maxt,dft*1000000);//最大时间
average+=dft*10000;
}
cout<<"顺序表查找成功最小时间为"<<mint<<"μs"<<endl;
outfile1<<"顺序表查找成功最小时间为"<<mint<<"μs"<<endl;
cout<<"顺序表查找成功最大时间为"<<maxt<<"μs"<<endl;
outfile1<<"顺序表查找成功最大时间为"<<maxt<<"μs"<<endl;
cout<<"顺序表查找成功平均时间为"<<average<<"μs"<<endl;
outfile1<<"顺序表查找成功平均时间为"<<average<<"μs"<<endl;
cout << endl;
outfile1 << endl;
outfile1<<"----------顺序表查找失败------------"<<endl;
for(int i=0;i<100;i++)
{
int x=no[i];
int count=0;//查找次数
QueryPerformanceCounter(&frequency);
bool flag=false;
begin_=frequency.QuadPart;//获得初始值
for(int j=0;j<n;j++)
{
count++;
if(num_list[j]==x)
{
flag=true;
break;
}
}
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(!flag)
{
cout<<"顺序表查找失败,查找次数为"<<count<<endl;
outfile1<<"顺序表查找失败,查找次数为"<<count<<endl;
}
mint=min(mint,dft*1000000);//最小时间
maxt=max(maxt,dft*1000000);//最大时间
average+=dft*10000;
}
cout<<"顺序表查找失败最小时间为"<<mint<<"μs"<<endl;
outfile1<<"顺序表查找失败最小时间为"<<mint<<"μs"<<endl;
cout<<"顺序表查找失败最大时间为"<<maxt<<"μs"<<endl;
outfile1<<"顺序表查找失败最大时间为"<<maxt<<"μs"<<endl;
cout<<"顺序表查找失败平均时间为"<<average<<"μs"<<endl;
outfile1<<"顺序表查找失败平均时间为"<<average<<"μs"<<endl;
cout<<"----------哈希查找----------"<<average<<"μs"<<endl;
outfile1<<"----------哈希查找----------"<<average<<"μs"<<endl;
mint=100000,maxt=0,average=0;
for(int i=0;i<100;i++)
{
bool flag=false;
int x=num_list[i];
int ke=x%maxn;
int y=C[ke];
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值1
if(y==x) flag=true;
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(flag)
{
cout<<"hash查找成功"<<endl;
outfile1<<"hash查找成功"<<endl;
}
mint=min(mint,dft*1000000);//最小时间
maxt=max(maxt,dft*1000000);//最大时间
average+=dft*10000;
}
cout<<"hash查找成功最小时间为"<<mint<<"μs"<<endl;
outfile1<<"hash查找成功最小时间为"<<mint<<"μs"<<endl;
cout<<"hash查找成功最大时间为"<<maxt<<"μs"<<endl;
outfile1<<"hash查找成功最大时间为"<<maxt<<"μs"<<endl;
cout<<"hash查找成功平均时间为"<<average<<"μs"<<endl;
outfile1<<"hash查找成功平均时间为"<<average<<"μs"<<endl;
cout << endl;
outfile1<<"----------hash查找失败------------"<<endl;
mint=100000,maxt=0,average=0;
for(int i=0;i<100;i++)
{
bool flag=false;
int x=no[i];
int ke=x%maxn;
int y=C[ke];
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值1
if(y==x) flag=true;
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(flag){
cout<<"hash查找成功"<<endl;
outfile1<<"hash查找成功"<<endl;
}
else{
cout<<"hash查找失败"<<endl;
outfile1<<"hash查找失败"<<endl;
}
mint=min(mint,dft*1000000);//最小时间
maxt=max(maxt,dft*1000000);//最大时间
average+=dft*10000;
}
cout<<"hash查找失败最小时间为"<<mint<<"μs"<<endl;
outfile1<<"hash查找失败最小时间为"<<mint<<"μs"<<endl;
cout<<"hash查找失败最大时间为"<<maxt<<"μs"<<endl;
outfile1<<"hash查找失败最大时间为"<<maxt<<"μs"<<endl;
cout<<"hash查找失败平均时间为"<<average<<"μs"<<endl;
outfile1<<"hash查找失败平均时间为"<<average<<"μs"<<endl;
outfile1.close();
return 0;
}
/*#include <iostream>
#include <time.h>
#include <algorithm>
#include <fstream>
#include <windows.h>
using namespace std;
LARGE_INTEGER frequency;
double dff,begin_,_end,dfm,dft;
int main()
{
QueryPerformanceFrequency(&frequency);//获得时钟频率
dff=(double)frequency.QuadPart;//取得频率
int yes[100],no[100];
ifstream input1("success.txt");
for(int i = 0 ; i < 100; i++)
input1 >> yes[i];
input1.close();
ifstream input2("fail.txt");
for(int i = 0 ; i < 100; i++)
input2 >> no[i];
input2.close();
return 0;
}
*/
随机数生成代码:
#include <iostream>
#include <time.h>
#include <algorithm>
#include <vector>
#include <fstream>
using namespace std;
const int max_size = 1024*1024;//10M大小
int main()
{
srand((int)time(NULL));//重置时间种子
//string files[7]={"100.txt","1K.txt","10K.txt","100K.txt","1M.txt","success.txt","fail.txt"};
//int myarray[max_size];
vector<int> num_list;
vector<int> yes_list;
ofstream outfile("1M.txt");
for(int i = 0 ; i < max_size ; i++)
{
int k= rand()%max_size;
num_list.push_back(k);
outfile <<num_list[i] << " ";
if((i+1) % 10 == 0)
outfile << endl;
}
outfile.close();
ofstream outfile5("success.txt");
for(int i = 0 ; i < 100 ; i++)
{
int k = rand()%max_size;
if (find(num_list.begin(), num_list.end(), k) != num_list.end())
{
outfile5 << k << " ";
yes_list.push_back(k);
}
else
i--;
if((i+1) % 10 == 0)
outfile5 << endl;
/*vector<int>::iterator s=find(num_list.begin(),num_list.end(),k);
if( s !=array.end()) //找到
{
outfile << k;
}
else
i--;
*/
}
outfile5.close();
ofstream outfile6("fail.txt");
for(int i = 0 ; i < 100 ; i++)
{
int k = rand()%max_size+150;
if (find(num_list.begin(), num_list.end(), k) == num_list.end())
{
outfile6 << k << " ";
}
else
i--;
if((i+1) % 10 == 0)
outfile6 << endl;
/*vector<int>::iterator s=find(num_list.begin(),num_list.end(),k);
if( s ==array.end()) //找到
{
outfile << k;
}
else
i--;
*/
}
outfile6.close();
ofstream outfile1("100.txt");
for(int i = 0 ; i < 100 ; i++)
{
//int k = rand()%100;
outfile1 << yes_list[i] << " ";
if((i+1) % 10 == 0)
outfile1 << endl;
}
outfile1.close();
ofstream outfile2("1K.txt");
for(int i = 0 ; i < 1024 ; i++)
{
if(i < 100)
{
//int k = rand()%100;
outfile2 << yes_list[i] << " ";
}
else
{
int k = rand()%max_size;
outfile2 << num_list[k] << " ";
}
if((i+1) % 10 == 0)
outfile2 << endl;
}
outfile2.close();
ofstream outfile3("10K.txt");
for(int i = 0 ; i < 1024*10 ; i++)
{
if(i < 100)
{
//int k = rand()%100;
outfile3 << yes_list[i] << " ";
}
else
{
int k = rand()%max_size;
outfile3 << num_list[k] << " ";
}
if((i+1) % 10 == 0)
outfile3 << endl;
}
outfile3.close();
ofstream outfile4("100K.txt");
for(int i = 0 ; i < 1024*100 ; i++)
{
if(i < 100)
{
//int k = rand()%100;
outfile4 << yes_list[i] << " ";
}
else
{
int k = rand()%max_size;
outfile4 << num_list[k] << " ";
}
if((i+1) % 10 == 0)
outfile4 << endl;
}
outfile4.close();
cout << "随机数生成成功" << endl;
}