提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、实验目的
1、掌握基于线性表、二叉排序树和散列表不同存储结构的查找算法。
2、掌握不同检索策略对应的平均查找长度(ASL)的计算方法,明确不同检索策略的时间性能的差别。
二、设计内容
一篇英文文章存储在一个文本文件中,然后分别基于线性表、二叉排序树和哈希表不同的存储结构,完成单词词频的统计和单词的检索功能。同时计算不同检索策略下的平均查找长度ASL,通过比较ASL的大小,对不同检索策略的时间性能做出相应的比较分析(比较分析要写在实习报告中的“收获和体会”中)。
1. 读取一篇包括标点符号的英文文章(InFile.txt),假设文件中单词的个数最多不超过5000个。从文件中读取单词,过滤掉所有的标点。
2. 分别利用线性表(包括基于顺序表的顺序查找、基于链表的顺序查找、基于顺序表的折半查找)、二叉排序树和哈希表(包括基于开放地址法的哈希查找、基于链地址法的哈希查找)总计6种不同的检索策略构建单词的存储结构。
3. 不论采取哪种检索策略,完成功能均相同。
(1)词频统计
当读取一个单词后,若该单词还未出现,则在适当的位置上添加该单词,将其词频计为1;若该单词已经出现过,则将其词频增加1。统计结束后,将所有单词及其频率按照词典顺序写入文本文件中。其中,不同的检索策略分别写入6个不同的文件。
基于顺序表的顺序查找--- OutFile1.txt
基于链表的顺序查找--- OutFile2.txt
折半查找--- OutFile3.txt
基于二叉排序树的查找--- OutFile4.txt
基于开放地址法的哈希查找--- OutFile5.txt
基于链地址法的哈希查找--- OutFile6.txt
注:如果实现方法正确,6个文件的内容应该是一致的。
(2)单词检索
输入一个单词,如果查找成功,则输出该单词对应的频率,同时输出查找成功的平均查找长度ASL和输出查找所花费的时间。如果查找失败,则输出“查找失败”的提示。
实验提示:不同的检索策略所采取的数据结构不一样,算法实现的过程不一样,但查找结果是一样的。
三、测试数据
事先将一篇英文文章存储在文件InFile.txt中,例如下图所示:
四、源码
#include<iostream>
#include<fstream>
#include<cstring>
#include<string>
#include<windows.h>
#include<conio.h>
#include<cmath>
#include<time.h>
using namespace std;
#define MAXN 5005
#define CLOCKS_PER_SEC 1000
int sum;
//调整时间精度的函数
BOOL WINAPI QueryPerformanceFrequency(
_Out_ LARGE_INTEGER *lpFrequency
);
BOOL WINAPI QueryPerformanceCounter(
_Out_ LARGE_INTEGER *lpPerformanceCount
);
//时间类
/*函数调用时间*/
class stop_watch
{
public:
stop_watch()
: elapsed_(0)
{
QueryPerformanceFrequency(&freq_); ///返回硬件支持的高精度计数器的频率
}
~stop_watch(){} //时间停止,析构函数
/*时间开始函数*/
void start()
{
QueryPerformanceCounter(&begin_time_); ///是返回定时器的频率 ,获取时间
}
void stop()
{
LARGE_INTEGER end_time;
QueryPerformanceCounter(&end_time); //这里控制时间 ,获取时间
elapsed_ += (end_time.QuadPart - begin_time_.QuadPart) * 10000000 / freq_.QuadPart;
}
void restart()
{
elapsed_ = 0;
start();
}
//微秒
double elapsed()
{
return static_cast<double>(elapsed_);
}
//毫秒
double elapsed_ms()
{
return elapsed_ / 1000.0;
}
//秒
double elapsed_second()
{
return elapsed_ / 1000000.0;
}
private:
LARGE_INTEGER freq_;
LARGE_INTEGER begin_time_;
long long elapsed_;
};
typedef struct w{
char ch[30]; //单词数组
int num; //出现频率
}word;
word words[MAXN]; //结构数组
typedef struct ss{ //顺序表,哈希表
word *r; //数据域
int len; // 顺序表长度
}SqList;
typedef struct LNode{ //链表,哈希表
word data; //数据域
struct LNode *next; //下一结点
}LNode, *Linklist;
typedef struct BSTNode{ //二叉排序树
word data; //数据域
struct BSTNode *lch, *rch; //下一左节点, 下一右节点
}BSTNode, *BSTree;
void HomePage(); // 主目录 //一级目录
void Linearlist(); // /*线性表查找*/ //二级目录
void SqSearch(); // /*顺序表查询*/ //三级目录
void BiSearch(); // /*折半查找*/ //四级目录
void Sq_SqSearch(); // 基于顺序表的顺序查找
void Link_SqSearch(); // 基于链表的顺序查找
void BisortTree(); // 基于二叉排序树的查找
void HashTable(); // 基于哈希表的查找
void Openad_Hash(); // 基于开放地址法的哈希查找
void Linkad_Hash(); // 基于链地址法的哈希查找
void readfile(char essay[]); // 读取文件
void Insert(BSTree &T,word e); // 二叉树插入
void MTraverse(BSTree &T,FILE *fp); // 中序遍历将二叉排序树从小到大输出
void Hash(SqList &H,char *key,int k); // 哈希表,开放链地址
void Hash2(Linklist H[],char *key,int k); // 链地址法的数据插入
void WordSearch1(); // 基于顺序表的顺序查找 单词查找
void WordSearch2(); // 基于链表的顺序查找 单词查找
void WordSearch3(); // 基于顺序表的折半查找 单词查找
void WordSearch4(); // 基于二叉排序树查找 单词查找
void WordSearch5(); // 基于开放地址法的哈希查找 单词查找
void WordSearch6(); // 基于链地址法的哈希查找 单词查找
void WordfreStatistic1(); // 基于顺序表的顺序查找 词频统计
void WordfreStatistic2(); // 基于链表的顺序查找 词频统计
void WordfreStatistic3(); // 基于顺序表的折半查找 词频统计
void WordfreStatistic4(); // 基于二叉排序树的查找 词频统计
void WordfreStatistic5(); // 基于开放地址法的哈希查找 词频统计
void WordfreStatistic6(); // 基于链地址法的哈希查找 词频统计
void QSort1(SqList &L,int low,int high); // 顺序表排序
void QSort2(Linklist pbegin,Linklist pend); //链表排序
void QSort3(SqList &H,int low,int high); // 开放连地址法排序
int Partition1(SqList &L,int low,int high); // 排序
Linklist Partition2(Linklist pbegin,Linklist pend); //排序
int Partition3(SqList &H,int low,int high); // 排序
int Search_Seq(SqList &L,char c[]); // /* 查找单词位置*/ 顺序表
LNode* Search_link(Linklist &L,char c[]); // 基于链表查找 单词
int Search_Bin(SqList &L,char c[]); // 折半查找单词
BSTree Search_BST(BSTree T,char c[]); // 基于二叉树的查找单词
int Search_openha