《数据结构》课程设计报告书Word文档下载推荐.docx
《《数据结构》课程设计报告书Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《《数据结构》课程设计报告书Word文档下载推荐.docx(14页珍藏版)》请在冰豆网上搜索。
2.4处理冲突的方法3
三、设计思路3
3.1设计图示3
3.2函数功能说明4
3.2函数功能说明5
四、关键部分实现细节5
五、调试分析8
六、程序运行结果9
七、心得体会11
参考文献11
一、题目描述
1.1问题描述
扫描c源程序,利用hash技术统计该源程序中的关键字出现的频度。
1.2实现要求
先用Hash表存储c语言中32个关键字,再扫描c源程序取出每个单词,利用Hash查找技术统计该程序中的关键字出现的频度。
发生Hash冲突用线性探测法解决。
设Hash函数为:
Hash(key)=[(key的第一个字母序号)*100+(key的最后一个字母序号)]MOD41。
二、题目分析
2.1Hash函数
Hash函数就是把任意长度的输入通过散列算法,变换成固定长度的输出的一种转换。
该输出就是散列值。
这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一地确定输入值。
Hash函数主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的编码里。
因此也可以说,Hash函数就是一种数据内容和数据存放地址之间的映射关系。
2.2关键技术
统计C源程序中关键字出现的频度,主要分为这样几个关键技术:
是选择合适的Hash函数。
常用的Hash函数有直接定址法、除留余数法、数字分析法、平方取余法等众多种类,分别适合不同的问题要求。
Hash函数选择的好坏对发生冲突的概率有着很大影响,因而在很大程度上影响程序运行的效率。
是如何将所有关键字使用Hash函数存入比较数组中。
是字符串模式匹配技术。
即如何在众多程序代码中选择出C语言的关键字。
是文件输入输出技术。
这是整个方法的前提,即需要统计关键字个数的C源程序必须从文件中读入,才能进行处理。
处理后的结果还需要写入文件中进行保存。
2.3利用Hash函数统计C源程序中关键字出现频度的设计思想
使用Hash技术必须首先选择Hash函数。
基于对问题的分析,在此我们选用除留取余法建立Hash函数。
因为直接定址法虽然简单但会造成内存单元的大量浪费,而数字分析法、平方取中法等方法过于复杂,本身对时间资源的消耗过大,在本问题中使用并不值得。
我们建立的Hash函数为:
Hash(key)=[(key的第一个字母序号)*100+(key的最后一个字母序号)]%41
其中key为关键字,在本问题中为C源程序的关键字。
C语言关键字是C语言的保留的一些单词,这些单词都有了固定的意义和用途,不可以作为变量或者自定义类型或类名来使用。
其特点是都有小写字母构成。
定义一个多维数组,数组第一行存放关键字,数组第二行存储hash函数处理后关键字结点地址,用hash函数存储关键字。
2.4处理冲突的方法
选择再好的Hash函数也有出现冲突的可能,因此还必须选择一种解决Hash冲突的方法。
处理冲突的方法一般有开放定址法、线性探测法、二次探测法、链地址法等。
为了简单起见,我选择了线性探测法,即当发生冲突时,从冲突发生位置的下一个位置起,依次寻找空的Hash地址,如果该地址为空,就把该关键字存入相应的地址中。
三、设计思路
3.1设计图示
图1函数层次调用图
图2设计流程图
3.2函数功能说明
intOpen(char*filename)——————打开含关键字的CPP文件。
intFindHash(char*keyword)——————在Hash表中查找关键字找出关键字位置。
intCreatHash(char*keyword)——————建立Hash表,keyword是一个数组。
intInsert(intkey)——————在Hash表中插入关键字。
voidMenu()——————现实菜单。
voidPrintScreen(intkey)——————输出关键字。
intLetterNot(charch)——————判断单词是否扫描结束。
intKeywordsNot(char*word)——————判断是否为关键字。
intGetHashValue(char*keyword)——————得到关键字的哈希函数值。
四、关键部分实现细节
intOpen(char*filename)
{
charword[MaxLength],ch;
inti;
FILE*read;
//指向FILE类的指针*read
if((read=fopen(filename,"
r"
))==NULL)//只读方式读取文件,如果为空
{
printf("
未找到要打开的文件,请重新输入!
"
);
return-1;
//跳出Open函数
}
while(!
feof(read))//判断文件是否结束,到末尾函数值为"
真"
即非0
i=0;
ch=fgetc(read);
//读取一个字符
while(LetterNot(ch)==0&
&
feof(read)==0)
ch=fgetc(read);
//如果不是字母就接着读取,关键字都是由字母组成的
while(LetterNot(ch)==1&
{
if(i==MaxLength)
{
while(LetterNot(ch)==1&
{
ch=fgetc(read);
//超过MAXLEN的长度则一定不为关键字,把余下连一起的字母都读取
}
i=0;
break;
}
else
word[i++]=ch;
//把读取到的字母存入word数组中
ch=fgetc(read);
}
word[i]='
\0'
;
if(KeywordsNot(word))
CreatHash(word);
fclose(read);
printf("
文件中关键字已经存入表中,请继续!
intFindHash(char*keyword)//在Hash表中查找关键字
intkey,find,FindColl=0;
if(!
KeywordsNot(keyword))//是否关键字
key=GetHashValue(keyword);
if(strcmp(Test[key].keyword,keyword)==0)
returnkey;
for(find=key+1;
find<
LengthofHash;
find++)
{//线性探测法
FindColl++;
//FindColl统计冲突次数
if(strcmp(Test[find].keyword,keyword)==0)
Test[find].coll=FindColl;
//把冲突次数存入coll
returnfind;
for(find=0;
key;
find++)//后面的找不到再从前面开始找
return-1;
}
intCreatHash(char*keyword)//建立Hash表,keyword是一个数组
intkey;
KeywordsNot(keyword))//判断是否关键字
//计算Hash值
if(strlen(Test[key].keyword)>
0)//Hash表中该位置存在关键字
{
if(strcmp(Test[key].keyword,keyword)==0)//Hash表中该位置的关键字相同
{
Test[key].count++;
//频度加1
return1;
//跳出函数
key=FindHash(keyword);
//不相同,继续查找
if(key<
0)//没有找到相等的keyword
key=Insert(GetHashValue(keyword));
if(key<
0)//Hash表满或者计算的Hash值有问题
return-1;
strcpy(Test[key].keyword,keyword);
//将关键字插入Hash表
0)
return-1;
Test[key].count++;
else//该位置没有关键字
strcpy(Test[key].keyword,keyword);
return1;
intInsert(intkey)//在Hash表中插入关键字
intfind,FindColl=0;
if(key<
0||key>
=LengthofHash)
find++)//分块查找后部分
if(strlen(Test[find].keyword)==0)//若这个地方为空
Test[find].coll=FindColl;
//把冲突的次数存入coll中
returnfind;
find++)//分块在前部分查找
if(strlen(Test[find].keyword)==0)
//Hash表已满
五、调试分析
在调试过程中主要遇到两个问题:
一是怎么扫描到并打开cpp文件;
二是怎么判断一个单词是否结束。
经过查阅相关资料以后,了解到调用c语言的库函数fope,打开函数并以“r”方式依次读入cpp文件的字符,需要注意的是在指定文件名称的时候需要说明文件的存放位置以便找到文件,否则便会读入失败。
对于第二个问题采用判断读入的字符是否在“a”到“z”中间或者“A”到“Z”之间,并把读入字符存入keyword中。
如果是则一个单词未读入完成,如果不是则判定该单词完成,并把keyword字符数组和c语言关键字进行比对,如果是关键字则计算该关键字的哈希值并将该关键字存入相应的地址,就完成了一次完整的读入过程。
另外还有就是对于新读入的关键字要首先判断哈希表中是否已经存在了,先计算出关键字的哈希值,在哈希表中查找该位置是否是新读入的关键字,如果不是则按照线性处突法继续往后查找,如果没有找到则从哈希表开始的位置找到哈希值得位置,就可以判定该关键字是否存在的问题了。
其实对于一般的txt文件也可以用这个程序来判定某些特定字符出现的频度。
六、程序运行结果
七、心得体会
1.我又进一步巩固了C语言的基础,尤其是文件那部分。
2.通过程序加深了对Hash查找方面知识的认识。
更深一层次了解了Hash查找的优缺点。
3.做课程设计达到了理论与实践结合的目的,提高了自己的编程能力,
4.程序由算法和数据结构组成,一个好的程序不仅算法重要,数据结构的设计也很重要。
5.通过这次课程设计,我了解到自己在实践操作方面还有很多不足,在实践过程中老师和同学给了我很大的帮助和鼓励,学会了团结精神的重要性,以及做事必须一丝不苟,遇到困难不能半途而废要有不惧困难探求真理,踏踏实实的解决问题。
参考文献
C程序设计(第四版)谭浩强著清华大学出版社
数据结构(C语言版)严蔚敏吴伟民著清华大学出版社
以及部分网络资料