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