hash查找课程设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构
课程设计说明书利用Hash技术统计C源程序中关键字的频度
学院:计算机科学与工程学院
专业班级:***********************
学号:***************
学生姓名:***********
指导教师:**********
2013年 1 月 1 日***************课程设计(论文)任务书
2013 年1 月5 日
*********课程设计(论文)成绩评定表
目录
绪论 (2)
1需求分析 (3)
1.1概要设计 (3)
1.2 设计流程图 (4)
2详细设计 (5)
2.1主函数 (5)
2.2界面显示 (5)
2.3输入函数 (5)
2.4显示关键字的存在 (6)
2.5选择函数 (6)
2.6读取文件 (7)
2.7 判断是否是字母 (7)
2.8查找哈希表 (8)
2.9建立哈希表 (8)
2.10在哈希表中插如关键字 (8)
2.11重置哈希表 (9)
2.12判断是否是关键字 (9)
3执行结果 (10)
4总结 (12)
绪论
线性表、树等各种结构中,记录在结构的相对位置都是随机的,和记录的关键字之间不存在确定的关系,因此。

在结构中查找记录是需进行一系列和关键字的比较。

这一类查找方法建立在“比较”的基础上。

则查找的效率依赖于查找过程中所进行的比较次数。

理想的情况是希望不经过任何的比较,一次存取便能得到所差的记录,那就必须在记录的存储位置和它的关键字之间建立一个确定的对应的关系f,是每个关键字和结构中一个唯一的存储位置相对应,因而在查找时候,只要根据这个对应的关系f找到给定值K的像f (K)。

若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上,由此,不需要进行比较便可直接取得所查的记录。

在此,我们称这个对应关系f为哈希函数,按照这个思想建立得标为哈希表。

哈希函数是一个映像,因此哈希函数的设定很灵活,只要使得任何关键字由此所得的哈希函数都落在表长允许范围之内即可。

对不同的关键字可能得到同一个哈希地址,这种现象成冲突。

具有相同函数值的关键字对该哈希函数来说称做同义词。

然而,在一般情况下,冲突尽可能地少,而不能完全避免。

哈希函数的构造方法有五种:直接定址法、数字分析法、平方取中法、折叠法、除留余数法。

本次课程设计是用Hash表存储该程序中出现的关键字,并统计该程序中的关键字出现的度。

用线性探测法解决Hash冲突。

设Hash 函数为:Hash(Key)=[(Key的首字母序号)*100+(Key的尾字母序号)] Mod 41。

关键字39个。

其功能是:从一个大字符串中分解单词;识别是否是关键词;Hash函数,解决冲突,统计冲突次数。

key => 地址;插入Hash表,或调整Hash表项中的频度⑤输出Hash表,关键词总数,冲突次数。

本次课程设计是安徽理工大学学生完成,同时参考了很多的书籍和资料,同时在网上查阅了很多的有用信息。

由于学生能力有限,所以此次课程设计难免有很多的错误,希望大家指出和多提意见,让我多多的改正,谢谢各位读者。

1需求分析
1.1概要设计
首先读取关键字文件以建立二叉排序树以供后续查询,每个树节点保存一个关键字字符串及指向左右子树的指针。

同时创建一Hash 表,每个节点除应保存关键字字符串外,还应保存关键字频数及该存储单元冲突次数。

然后扫描一个C源程序,每次扫描一行,从中循环分离出每个单词,每次均查找其是否为关键字,若是,则按计算公式计算其KEY值并在Hash表中进行相应操作,若该节点为空则插入否者比较其是否与现有关键字相同,若相同则增加其频数,否则增加其冲突次数并继续线性探测下一个存储单元,完了继续操作下一个分离出来的单词,如此循环运行直至扫描结束。

编写本程序时,使用了二叉树创建、二叉树查找、Hash表的建立和操作及文件操作等基本算法。

本次程序设计中采用一个欢迎界面用来给用户选择,向其展示了可供选择的菜单,和用户想实现的功能。

在选择是可以通过数字进行选择,系统通过判断选择是否正确,输入后进行判断是否为空白符,当字符为空白符是返回非零值,否则返回零值,空白值是指空格、水平制表、垂直制表、换页、回车和换行符。

在可供选择的界面中,用户可以选择读取一个文件、输出关键字的总数以及冲突的次数、查询某关键字在hash表中的情况、显示hash表中的冲突关键、显示c语言关键字的hash函数值、回主菜单和退出整个程序,这些不同的选项中用户可以选择不同的功能以实现不同的目的。

在整个程序执行的开始要读取一个文件,该读取的文件必须与程序在同一目录下,这样方便程序可以读取到该文件,在读取该文件后,系统开始建立哈希表和插进关键字,之后开始重置哈希表,然后可以查找哈希表,在读取文件后进行判断是否为字母和关键字,最后系统将程序执行的结果输出来。

在整个系统中,应用了很多的函数来实现这些功能,这些函数是界面、展示、选择、读取、输入、是否是字母、查找哈希、建立哈希、插进关键字、重置哈希表和是否是关键字,每个函数都有其不同的功能,用来完成不同的目的。

1.2 设计流程图
(本实验流程图)
2详细设计
2.1主函数
该函数是主函数用来提示用户,同时可执行其他函数。

void main(){
system("COLOR 9f");
ResetHX(); //先清空哈希表
cout<<"\t======================================"<<endl;
·········
cout<<"\t======================================"<<endl;
cout<<"\t===================================="<<endl
<<endl; system("pause");system("cls");jiemian();Select(Input());} 2.2界面显示
界面显示用来显示菜单可供用户来选择菜单以实现不同的功能void jiemian()
{ system("COLOR 6f");
cout<<endl;
cout<<"\t\t1.读取一个文件"<<endl;
cout<<"\t\t2.输出Hash表(关键字总数,冲突次数)"<<endl;
cout<<"\t\t3.查询某关键字在Hash表中的情况"<<endl;
cout<<"\t\t4.显示Hash表中的冲突关键字"<<endl;
cout<<"\t\t5.显示C语言······(作为对照)"<<endl;
cout<<"\t\t6.回主菜单"<<endl;
cout<<"\t\t7.退出"<<endl; }
2.3输入函数
该函数是用来供用户选择不同的功能,以供系统执行不同的函数,来实现不同的功能。

int Input()
{ cout<<endl;
cout<<"按'6'回主菜单,请输入你的选择(1-7): ";
while(true) //确保输入的为数字{
int choice=0;if((cin>>choice)){
if((choice<=0)||(choice>7))
cout<<"输入范围不正确,请重新输入"<<endl; }
else{
cout<<"输入错误,请重新输入"<<endl;
cin.clear();}
while(!isspace(cin.get())) //功能:判断字符是否为空白符//空白符指空格、垂直制表、换页、回车和换行符。

continue; cout<<endl; return choice; } }
2.4显示关键字的存在
该函数只是用来将用户查找的关键字是否存在,同时将结果显示出来的函数。

void Show(int key){ if(key<0||key>=HASHLEN){
cout<<"关键字不存在!"<<endl; return;}
if(strlen(HS[key].keyword)==0)
{ cout<<"哈希表位置:"<<key<<" 记录是空的"<<endl;
return ;}
cout<<"哈希表位置: "<<key<<" 关键字: "
<<HS[key].keyword<<" 出现次数"<<HS[key].count<<endl;
cont++;}
2.5选择函数
当用户选择了不同的功能后,系统开始执行其不同的程序以实现不同的功能。

void Select(int choice){
char filename[128],word[MAXLEN];
int i,key,count; switch(choice){
case 1:cout<<"请输入要······程序在同一目录下):";
cin>>filename; cout<<endl;
Read(filename); Select(Input()); break;
··········
return; } }
2.6读取文件
在程序的同一个目录下,系统可以读取文件,该读取的文件可以用来判断用户所需的结果。

int Read(char *filename) //读取文件{
char word[MAXLEN],ch; int i; FILE *read;
if( (read=fopen(filename,"r"))==NULL ) {
cout<<"文件不存在,请确认好再输入!"<<endl;
return -1;}
ResetHX(); //读取文件前先清空哈希表
while(!feof(read)) // { i=0;
ch=fgetc(read); //读取一个字符
while(isLetter(ch)==0 && feof(read)==0 ) ch=fgetc(read);
while(isLetter(ch)==1 && feof(read)==0 ){
if(i==MAXLEN){
while(isLetter(ch)==1&& feof(read)==0){
ch=fgetc(read); } i=0; break;} else
{ word[i++]=ch; ch=fgetc(read); } }
word[i]='\0'; //字符数组的结束标志if(isKeyWords(word)){
CreatHX(word); } } fclose(read);
cout<<"读取成功·······请继续操作"<<endl;
jiemian(); r eturn 1; }
2.7 判断是否是字母
该段函数用来判断是否是字母,因为关键字都是英文单词
int isLetter(char ch) {
if( (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z') ) return 1;
else return 0;}
2.8查找哈希表
该段函数是用来查找哈希表,分块查找
int FindHX(char *keyword) { int key,find,tem=0;
if(!isKeyWords(keyword)) return -1;
key=GetKey(keyword);
if(strcmp(HS[key].keyword,keyword)==0) return key;
for(find=key+1;find<HASHLEN;find++)
{ em++; if(strcmp(HS[find].keyword,keyword)==0){ HS[find].con=tem; return find; } }
for(find=0;find<key;find++) { tem++;
if(strcmp(HS[find].keyword,keyword)==0){ HS[find].con=tem;
return find; } } return -1; }
2.9建立哈希表
该段函数是用来建立哈希表
int CreatHX(char *keyword) { int key;
if(!isKeyWords(keyword)) return -1;
key=GetKey(keyword); //计算哈希值
if(strlen(HS[key].keyword)>0) {
if(strcmp(HS[key].keyword,keyword)==0){ HS[key].count++;
return 1; } key=FindHX(keyword); if(key<0){
key=GetFreePos(GetKey(keyword)); if(key<0) return -1;
strcpy(HS[key].keyword,keyword); }
if(key<0) return -1; HS[key].count++; }
else { strcpy(HS[key].keyword,keyword);
HS[key].count++;} return 1; }
2.10在哈希表中插如关键字
该段函数是用来在哈希表中给关键字找个位置插进去
int GetFreePos(int key) { int find,tem=0;
if(key<0||key>=HASHLEN) return -1;
for(find=key+1;find<HASHLEN;find++) { tem++;
if(strlen(HS[find].keyword)==0){ HS[find].con=tem;
return find; } }
for(find=0;find<key;find++) { tem++;
if(strlen(HS[find].keyword)==0){ HS[find].con=tem;
return find; } } return -1; }
2.11重置哈希表
该段函数是用来重置哈希表,
void ResetHX() { int i; for(i=0;i<HASHLEN;i++) {
strcpy(HS[i].keyword,""); HS[i].count=0; HS[i].con=0;}}
int GetKey(char *keyword) { //Hash函数为:Hash(Key)=[(Key 的首字母序号)*100+(Key的尾字母序号)] Mod 41
return ( keyword[0]*100+keyword[strlen(keyword)-1] ) % 41; //
}
2.12判断是否是关键字
该段函数再整系统中是用来判断是否关键字
int isKeyWords(char *word) { int i; for(i=0;i<TOTAL;i++)
if(strcmp(word,KeyWords[i])==0) return 1; r eturn 0;}
3执行结果
欢迎界面的执行结果(图1)
图1 读取文件的执行结果(图2)
图2 选择菜单的执行结果(图3)
图3
显示hash表中冲突关键字的执行结果(图4)
图4
显示c语言关键字的hash值的执行结果(图5)
图5
4总结
通过本次课程设计我系统的了解到了哈希表的建立、使用、以及在程序中的使用及其的优越性。

这次做课程设计,是一次完整的播种与收获的过程,为它挥汗,因它烦忧,同时也因它而雀跃。

在写代码期间,每天长时间坐在电脑显示器前面,酸胀的眼睛,手旁满是手工演算的草稿,有时为了实现某个功能绞尽脑汁,坐站都不是。

当程序遇到问题运算结果与演算结果不匹配而又怎么也找不到问题的所在时,那个痛苦和烦恼,真的是很让人难以忘怀的。

当然,也有快乐的时候,那自然是当顺利实现某方面功能的时候。

编程需要有耐心,尤其实在单步调试的时候,更是马虎不得,有时候关键就是那么一步,错过了就得从头来过了。

编程也需要勇气,要勇于发现自己的错误,也要勇于推翻自己之前的思路,要坚信“没有最好,只有更好”。

编程,最好是一鼓作气,得天天“摸摸”它,时时想着它,要是过一阵再去碰它那就得先去读懂自己的程序了,一切的一切几乎都得从头开始。

编程需要细心,有时一个不注意小错误就能引出大问题。

编程也需要规范,不仅为了他人能看得懂程序,也为了方便自己以后程序的更改与进一步的完善。

同时在做课程设计的时候我才更家的了解我知识匮乏,同时感到我学的的东西只不过是一个皮毛而已,我深深的知道我所要学习的东西,和在未来的道路上我还要继续的努力和拼搏,编程这门博大而精深的学科,我将无所畏惧的走下去。

总之,做完课程设计使我感觉成长了许多,有艰辛的付出才会有收获,它使我收获了那份喜悦,更使我增强了自信心。

相关文档
最新文档