实验 8 查找算法实验比较
实验目的 基于教材内容,从顺序查找、二分查找、基于 BST 的查找和哈希中任选两种查找算法, 实现并比较性能。
基本要求 (1)对实现的查找算法进行实验比较,在不同数据规模(N)下执行 100次成功查找, 以表格形式记录最小、最大和平均查找时间;在不同数据规模(N)下执行 100 次不成功查 找,以表格形式记录最小、最大和平均查找时间。 (2)查找算法要基于教材,测试输入的整数数据文件(5 个,文件中数据规模 N 分别 是 100,1K,10K,100K 和 1M),每次查找的比较次数和时间要输出到文件中。 (3)提交最终实验作业。用附件的形式,提交两个文件:一个压缩包(包含源码和 5 个用于查找测试的数据文件);一个 pdf 文档(文档中包含实验日志和一个根据基本要 求(1)记录实验结果的表格,然后进行适当的实验结果分析)
注意:
首先要有一个叫“success”的文件,这个文件加上随机数的那条(第一条)代码运行,运行结果生成了fail,100,1k,10k,100k,1M的文件。 如果直接下载测试文档那么久不用生成测试文件,就能直接跑第二条代码查找了。 success文件除了自己下载外还可以自己在TXT里面填一个,改名为success就行了
下载测试文档
(1)首先生成测试数据用于测试:(只需要下载文档中的 “success”)
#include <iostream>
#include <time.h>
#include <fstream>
//***本程序用于产生随机数据
using namespace std;//RAND_MAX=32767
const int maxn=1048576;
int A[maxn]={0};
int Size[5]={100,1024,10240,102400,1048576};//文件大小
void Init(ifstream &infile,int& count)
{
int a;
while(!infile.eof())
{
infile>>a;
A[count]=a;
count++;
}
}
void print(ofstream &outfile,int n)//输出
{
for(int i=0;i<n;i++)
{
outfile<<A[i]<<' ';
}
}
int main()
{
int n=0;
//ifstream
ofstream out_100("100.txt"),out_1k("1k.txt"),out_10k("10k.txt"),out_100k("100k.txt"),out_1M("1M.txt")
,fail("fail.txt");//输入代查找数据;
ifstream sucess("sucess.txt");//读入
Init(sucess,n);//读入文件
srand(time(NULL));//时间种子
//生成测试文件
for(int i=100;i<Size[0];i++) A[i]=rand()%maxn;//得到[0,maxn)内的数
print(out_100,Size[0]);
for(int i=100;i<Size[1];i++) A[i]=rand()%maxn;//得到[0,maxn)内的数
print(out_1k,Size[1]);
for(int i=100;i<Size[2];i++) A[i]=rand()%maxn;//得到[0,maxn)内的数
print(out_10k,Size[2]);
for(int i=100;i<Size[3];i++) A[i]=rand()%maxn;//得到[0,maxn)内的数
print(out_100k,Size[3]);
for(int i=100;i<Size[4];i++) A[i]=rand()%maxn;//得到[0,maxn)内的数
print(out_1M,Size[4]);
//生成待查找数据
for(int i=0;i<100;i++) A[i]=rand()%maxn+maxn;//得到[maxn,2*maxn)内的数
print(fail,100);
}
(2)接下来是对每一组测试数据分别进行100次成功和失败查找
1.采用的是hash查找和二分查找,分别测试查找性能。
2.输出信息汇总在TXT文件里,另外整体数据的平均查找时间以及最大最小查找时间需要分别手动填写在一个表格里(数据量很少)
#include <iostream>
#include <time.h>//time类
#include <iomanip>
#include <windows.h>//这些头文件定义了Windows的所有资料型态、函数调用、
//资料结构和常数识别字,它们是Windows文件中的一个重要部分。
#include <fstream>//文件流
#include <algorithm>
using namespace std;
LARGE_INTEGER frequency;
int S[105]={0},F[105]={0};//成功查找和失败查找待查找数据
const int maxn=1048576;//数组上界1048576
int A[maxn+5]={0},H[maxn+5]={0};//测试数据A[maxn],B[maxn]
double dff,begin_,_end,dfm,dft;//时钟的频率,起始,实际时间差
void Init(ifstream &infile,int M[maxn])//从文件输入
{
int a,i=0;
while(!infile.eof()&&i<maxn)
{
infile>>a;
M[i]=a;
i++;
}
}
void Init(ifstream &infile,int M[maxn],int N[maxn])//从文件输入
{
int a,i=0,key;
fill(N,N+maxn,-1);//初始化
while(!infile.eof()&&i<maxn)
{
infile>>a;
M[i]=a;
key=a%maxn;
N[key]=a;//key(x)=x;hash函数定义为线性hash
i++;
}
}
void search_binary(ofstream& outfile,int A[maxn],int n)//二分查找
{
sort(A,A+n);//升序排列
int mid,num=0,x,left,right;//中间值和比较次数
double mints=100,maxts=0,averages=0;
double mintf=100,maxtf=0,averagef=0;
bool flag;
cout<<"-------------------二分查找成功--------------------\n";outfile<<"-------------------二分查找成功--------------------\n";
for(int i=0;i<100;i++)//100次成功查找
{
x=S[i];//确定待查找的数x
num=0;//初始化查找次数为0
left=0,right=n-1;
flag=0;
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值
while(left<=right)//二分查找
{
num++;//比较次数加一
mid=(left+right)/2;//mid=left+(right-left)/2;//防止溢出
if(A[mid]==x)
{
flag=1;//查找成功
break;
}
else if(A[mid]>x) right=mid-1;//避免相邻区间整形/2,查找不倒的情况
else left=mid+1;
}
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(flag)//查找成功
{
cout<<"二分查找记录->"<<x<<"->成功 "<<"查找次数: "<<num<<"次";
outfile<<"二分查找记录:"<<x<<"->成功 "<<"查找次数: "<<num<<"次";
}
else
{
cout<<"二分查找记录->"<<x<<"->失败 "<<"查找次数: "<<num<<"次";
outfile<<"二分查找记录:"<<x<<"->失败 "<<"查找次数: "<<num<<"次";
}
cout<<"查找时间: "<<dft*1000<<"ms"<<endl;
outfile<<"查找时间: "<<dft*1000<<"ms"<<endl;
mints=min(mints,dft*1000);//最小时间
maxts=max(maxts,dft*1000);//最大时间
averages+=dft*10;//平均时间
}
cout<<"\n-------------------二分查找失败--------------------\n";outfile<<"-------------------二分查找失败--------------------\n";
for(int i=0;i<100;i++)//100次失败查找
{
x=F[i];//确定待查找的数x
num=0;//初始化查找次数为0
left=0,right=n-1;
flag=0;
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值
while(left<=right)//二分查找
{
num++;//比较次数加一
mid=(left+right)/2;//mid=left+(right-left)/2;//防止溢出
if(A[mid]==x)
{
flag=1;
break;
}
else if(A[mid]>x) right=mid-1;//避免相邻区间整形/2,查找不倒的情况
else left=mid+1;
}
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(flag)//查找成功
{
cout<<"二分查找记录->"<<x<<"->成功 "<<"查找次数: "<<num<<"次";
outfile<<"二分查找记录:"<<x<<"->成功 "<<"查找次数: "<<num<<"次";
}
else
{
cout<<"二分查找记录->"<<x<<"->失败 "<<"查找次数: "<<num<<"次";
outfile<<"二分查找记录:"<<x<<"->失败 "<<"查找次数: "<<num<<"次";
}
cout<<"查找时间: "<<dft*1000<<"ms"<<endl;
outfile<<"查找时间: "<<dft*1000<<"ms"<<endl;
mintf=min(mintf,dft*1000);//最小时间
maxtf=max(maxtf,dft*1000);//最大时间
averagef+=dft*10;//平均时间
}
cout<<"二分查找成功:\n最小查找时间mints="<<mints<<"ms "<<"最大查找时间maxts="<<maxts<<"ms "<<"平均查找时间averages="<<averages<<"ms\n查找结束";
outfile<<"二分查找成功:\n最小查找时间mints="<<mints<<"ms "<<"最大查找时间maxts="<<maxts<<"ms "<<"平均查找时间averages="<<averages<<"ms\n查找结束";
cout<<"二分查找失败:\n最小查找时间mintf="<<mintf<<"ms "<<"最大查找时间maxtf="<<maxtf<<"ms "<<"平均查找时间averagef="<<averagef<<"ms\n查找结束";
outfile<<"二分查找成功:\n最小查找时间mints="<<mintf<<"ms "<<"最大查找时间maxtf="<<maxtf<<"ms "<<"平均查找时间averagef="<<averagef<<"ms\n查找结束";
}
void search_hash(ofstream &outfile,int H[maxn])//hash散列查找
{
int x,num=1,key,y;
double mints=100,maxts=0,averages=0;
double mintf=100,maxtf=0,averagef=0;
bool flag;
cout<<"-------------------hash查找成功--------------------\n";outfile<<"-------------------hash查找成功--------------------\n";
for(int i=0;i<100;i++)//100次失败查找
{
flag=0;
x=S[i],key=x%maxn,y=H[key];
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值
if(y==x) flag=1;//查找成功
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(flag)
{
cout<<"hash查找记录:"<<x<<"->成功 "<<"查找次数:"<<num<<" 次";
outfile<<"hash查找记录:"<<x<<"->成功 "<<"查找次数:"<<num<<" 次";
}
else
{
cout<<"hash查找记录:"<<x<<"->失败 "<<"查找次数:"<<num<<" 次";
outfile<<"hash查找记录:"<<x<<"->失败 "<<"查找次数:"<<num<<" 次";
}
cout<<"查找时间: "<<dft*1000<<"ms"<<endl;
outfile<<"查找时间: "<<dft*1000<<"ms"<<endl;
mints=min(mints,dft*1000);//最小时间
maxts=max(maxts,dft*1000);//最大时间
averages+=dft*10;//平均时间
}
cout<<"-------------------hash查找失败--------------------\n";outfile<<"-------------------hash查找失败--------------------\n";
for(int i=0;i<100;i++)//100次失败查找
{
flag=0;
x=F[i],key=x%maxn,y=H[key];
QueryPerformanceCounter(&frequency);
begin_=frequency.QuadPart;//获得初始值
if(y==x) flag=1; //查找成功
QueryPerformanceCounter(&frequency);
_end=frequency.QuadPart;//获得终止值
dfm=(double)(_end-begin_);//差值
dft=dfm/dff;//差值除以频率得到时间
if(flag)
{
cout<<"hash查找记录:"<<x<<"->成功 "<<"查找次数:"<<num<<" 次";
outfile<<"hash查找记录:"<<x<<"->成功 "<<"查找次数:"<<num<<" 次";
}
else
{
cout<<"hash查找记录:"<<x<<"->失败 "<<"查找次数:"<<num<<" 次";
outfile<<"hash查找记录:"<<x<<"->失败 "<<"查找次数:"<<num<<" 次";
}
cout<<"查找时间: "<<dft*1000<<"ms"<<endl;
outfile<<"查找时间: "<<dft*1000<<"ms"<<endl;
mintf=min(mintf,dft*1000);//最小时间
maxtf=max(maxtf,dft*1000);//最大时间
averagef+=dft*10;//平均时间
}
cout<<"hash查找成功:\n最小查找时间mints="<<mints<<"ms "<<"最大查找时间maxts="<<maxts<<"ms "<<"平均查找时间averages="<<averages<<"ms\n查找结束";
outfile<<"hash查找成功:\n最小查找时间mints="<<mints<<"ms "<<"最大查找时间maxts="<<maxts<<"ms "<<"平均查找时间averages="<<averages<<"ms\n查找结束";
cout<<"hash查找失败:\n最小查找时间mintf="<<mintf<<"ms "<<"最大查找时间maxtf="<<maxtf<<"ms "<<"平均查找时间averagef="<<averagef<<"ms\n查找结束";
outfile<<"hash查找失败:\n最小查找时间mintf="<<mintf<<"ms "<<"最大查找时间maxtf="<<maxtf<<"ms "<<"平均查找时间averagef="<<averagef<<"ms\n查找结束";
}
int main()
{
QueryPerformanceFrequency(&frequency);//获得时钟频率
dff=(double)frequency.QuadPart;//取得频率*/
ifstream in_100("100.txt"),in_1k("1k.txt"),in_10k("10k.txt"),in_100k("100k.txt"),in_1M("1M.txt");//输出测试数据文件
ifstream sucess("sucess.txt"),fail("fail.txt");//输入代查找数据
ofstream out_100("out_100.txt"),out_1k("out_1k.txt"),out_10k("out_10k.txt"),out_100k("out_100k.txt"),out_1M("out_1M.txt");
Init(sucess,S);//输入查找数据
Init(fail,F);//输入查找数据
Init(in_100,A,H);//初始化
cout<<"对规模为100的文件进行查找:"<<endl;out_100<<"对规模为100的文件进行查找:"<<endl;
cout<<"hash散列查找开始:\n";
search_hash(out_100,H);//二分查找
cout<<"-------------------------------------------\n";out_100<<"-------------------------------------------\n";
cout<<"二分查找开始:\n";
search_binary(out_100,A,100);//二分查找
Init(in_1k,A,H);//初始化
cout<<"对规模为1k的文件进行查找:"<<endl;out_1k<<"对规模为1k的文件进行查找:"<<endl;
cout<<"hash散列查找开始:\n";
search_hash(out_1k,H);//二分查找
cout<<"-------------------------------------------\n";out_1k<<"-------------------------------------------\n";
cout<<"二分查找开始:\n";
search_binary(out_1k,A,1024);//二分查找
Init(in_10k,A,H);//初始化
cout<<"对规模为10k的文件进行查找:"<<endl;out_10k<<"对规模为10k的文件进行查找:"<<endl;
cout<<"hash散列查找开始:\n";
search_hash(out_10k,H);//二分查找
cout<<"-------------------------------------------\n";out_10k<<"-------------------------------------------\n";
cout<<"二分查找开始:\n";
search_binary(out_10k,A,10240);//二分查找
Init(in_100k,A,H);//初始化
cout<<"对规模为100k的文件进行查找:"<<endl;out_100k<<"对规模为100k的文件进行查找:"<<endl;
cout<<"hash散列查找开始:\n";
search_hash(out_100k,H);//二分查找
cout<<"-------------------------------------------\n";out_100k<<"-------------------------------------------\n";
cout<<"二分查找开始:\n";
search_binary(out_100k,A,102400);//二分查找
Init(in_1M,A,H);//初始化
cout<<"对规模为1M的文件进行查找:"<<endl;out_1M<<"对规模为1M的文件进行查找:"<<endl;
cout<<"hash散列查找开始:\n";
search_hash(out_1M,H);//二分查找
cout<<"-------------------------------------------\n";out_1M<<"-------------------------------------------\n";
cout<<"二分查找开始:\n";
search_binary(out_1M,A,1048576);//二分查找
return 0;
}