《数据结构》课程设计哈希表设计.docx
- 文档编号:26631148
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:26
- 大小:94.56KB
《数据结构》课程设计哈希表设计.docx
《《数据结构》课程设计哈希表设计.docx》由会员分享,可在线阅读,更多相关《《数据结构》课程设计哈希表设计.docx(26页珍藏版)》请在冰豆网上搜索。
《数据结构》课程设计哈希表设计
目录
课程设计任务书2
1.问题描述3
1.1问题描述3
1.2基本要求3
1.3测试数据3
2.实现分析3
3.程序设计4
3.1存储结构设计4
3.2主要算法设计4
3.2.1程序主要函数原型及功能4
3.2.2各函数的实现5
3.2.3函数模块9
3.2.4程序流程图9
4.调试报告11
4.1调试中的问题11
4.2对设计和编码的讨论和分析11
5.程序运行结果11
6.经验和体会13
6.1感受和体会13
6.2对算法改进的想法15
7.哈希表和源程序15
7.1哈希表15
7.2源程序16
本科生课程设计成绩评定表21
课程设计任务书
学生姓名:
专业班级:
班
指导教师:
工作单位:
计算机科学系
题目:
哈希表设计
初始条件:
针对某个集体(比如你所在的班级)中的“人名”设计一个哈希表,使得平均查找长度不超过R,完成相应的建表和查表程序。
假设人名为中国人姓名的汉语拼音形式。
待填入哈希表的人名共有30个,取平均查找长度的上限为2。
哈希函数用除留余数法构造,用伪随机探测再散列发处理冲突。
测试用例见题集p166。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
课程设计报告按学校规定格式用A4纸打印(书写),并应包含如下内容:
1、问题描述
简述题目要解决的问题是什么。
2、设计
存储结构设计、主要算法设计(用类C语言或用框图描述)、测试用例设计;
3、调试报告
调试过程中遇到的问题是如何解决的;对设计和编码的讨论和分析。
4、经验和体会(包括对算法改进的设想)
5、附源程序清单和运行结果。
源程序要加注释。
如果题目规定了测试数据,则运行结果要包含这些测试数据和运行输出,
6、设计报告、程序不得相互抄袭和拷贝;若有雷同,则所有雷同者成绩均为0分。
时间安排:
1、第19周完成。
2、7月1日14:
00到计算中心检查程序、交课程设计报告、源程序(CD盘)。
指导教师签名:
年月日
系主任(或责任教师)签名:
年月日
课程设计报告书
1.问题描述
1.1问题描述
针对某个集体(比如你所在的班级)中的“人名”设计一个哈希表,使得平均查找长度不超过R,完成相应的建表和查表程序。
1.2基本要求
假设人名为中国人姓名的汉语拼音形式。
待填入哈希表的人名共有30个,取平均查找长度的上限为2。
哈希函数用除留余数法构造,用伪随机探测再散列发处理冲突。
1.3测试数据
取自己班级成员的名字作为测试数据,建立一个相关哈希表,并计算平均查找长度,完成查询。
2.实现分析
(1)针对某个集体中的人名设计一个哈希表,使得平均查找长度不超过R,完成相应的建立和查表程序。
(2)人名为汉语拼音形式,最长不超过19个字符(如:
庄双双zhuangshuangshuang)。
(3)假设待填入哈希表的人名有30个,平均查找长度的上限为2。
哈希表用除留余数法构造,用伪随机探测在散列法处理冲突。
(4)如果随机函数自行构造,则应首先调整好随机函数,使其分布均匀。
字符的取码方法可直接利用C语言中的toascii函数,并可对过长人名先进行折叠处理。
(5)查找成功时,显示姓名及关键字,并计算和输出查找成功的平均查找长度。
3.程序设计
3.1存储结构设计
根据哈希函数可唯一确定一个记录的地址,在理想情况下,记录就可以按照这个存储地址进行存储。
因此哈希表的存储结构可以是链表和线性表,但一般情况下选择线性表进行存储。
本次课程设计用到的存储结构如下:
typedefstruct
{char*name;//名字的拼音
intk;//名字拼音所对应的关键字
}NAME;//结构体NEMA,存放名字列表
typedefstruct//哈希表
{char*name;//名字的拼音
intk;//名字拼音所对应的关键字
intsi;//名字的查找长度
}HASH;//结构体HASH,哈希表
3.2主要算法设计
3.2.1程序主要函数原型及功能
[1]首先定义两个结构体数组:
NAMENameList[HASH_LENGTH];//全局变量NAME,存储原始姓名
HASHHashList[HASH_LENGTH];//全局变量HASH,存储哈希表中的姓名
[2]主要函数原型及功能:
voidInitNameList()
功能:
主要完成初始化姓名列表,并且将字符串的各个字符所对应的ASCII码相加,所得的整数作为哈希表的关键字。
以便利用关键字和除留余数法得到每个姓名的哈希地址。
voidCreateHashList()
功能:
构建一个哈希表并进行初始化;利用各个姓名的关键字得到哈希地址,将各个姓名按哈希地址进行存储,如果发生冲突,则利用伪随机探测再序列解决冲突,最终将姓名全部存放在哈希表中。
voidFindList()
功能:
对用户输入的姓名进行查找;查找结果分两种情况:
(1)查找成功,则输出姓名、关键字和查找长度;
(2)查找失败,则返回相应的失败信息。
查找时关键字的求法和处理冲突的方法与函数InitNameList()、CreateHashList()中的相关算法一致。
voidShowHash()
功能:
完成度已经建立好的哈希表进行输出显示,并输出平均查找长度。
voidmain()
功能:
完成对个函数的调用和与用户的交互。
3.2.2各函数的实现
(1)初始化姓名列表:
Ø哈希地址方法:
将字符串的各个字符所对应的ASCII码相加,所得的整数做为哈希表的关键字key。
Ø函数voidInitNameList()的实现(以班级30人的人名作为初始值):
voidInitNameList()//姓名(结构体数组)初始化
{char*f;
intr,s0,i;
NameList[0].name="fanxu";
NameList[1].name="jiangyong";
NameList[2].name="guyuze";
NameList[3].name="liuzhenhai";
NameList[4].name="chenang";
NameList[5].name="caoyandong";
NameList[6].name="yangchenchen";
NameList[7].name="shenjin";
NameList[8].name="puping";
NameList[9].name="luhaibo";
NameList[10].name="renchao";
NameList[11].name="wangshichuang";
NameList[12].name="guoqihui";
NameList[13].name="chengkang";
NameList[14].name="wangyuesong";
NameList[15].name="liangfangping";
NameList[16].name="wangxufeng";
NameList[17].name="hejie";
NameList[18].name="yangyiming";
NameList[19].name="wushengping";
NameList[20].name="yangchaoqin";
NameList[21].name="wulinfeng";
NameList[22].name="xiehongwei";
NameList[23].name="liushuo";
NameList[24].name="yijiabin";
NameList[25].name="xuhaiyang";
NameList[26].name="yangwenjuan";
NameList[27].name="chenjunyan";
NameList[28].name="wangjiaxin";
NameList[29].name="chenwan";
for(i=0;i {s0=0; f=NameList[i].name; for(r=0;*(f+r)! ='\0';r++)/*哈希地址方法: 将字符串的各个字符所对应的ASCII码相加,所得的整数作为哈希表的关键字*/ s0=*(f+r)+s0; NameList[i].k=s0; } } (2)建立哈希表 Ø用除留余数法构建哈希函数 Ø用伪随机探测再散列法处理冲突 Ø构建哈希函数voidCreateHashList()的实现: voidCreateHashList() {inti; for(i=0;i {HashList[i].py=""; HashList[i].k=0; HashList[i].si=0; } for(i=0;i {intsum=0; intadr=(NameList[i].k)%M;//哈希函数 intd=adr; if(HashList[adr].si==0)//如果不冲突 {HashList[adr].k=NameList[i].k; HashList[adr].py=NameList[i].py; HashList[adr].si=1; } else//冲突 {do {d=(d+NameList[i].k%10+1)%M;//伪随机探测再散列法处理冲突 sum=sum+1;//查找次数加1 }while(HashList[d].k! =0); HashList[d].k=NameList[i].k; HashList[d].py=NameList[i].py; HashList[d].si=sum+1; } } } (3)查找哈希表 Ø若查找成功,则输出姓名、关键字和查找长度;查找失败,则返回相应的失败信息。 Ø查找函数voidFindList()的实现: voidFindList()//查找 {charname[20]={0}; ints0=0,r,sum=1,adr,d; printf("请输入姓名的拼音: "); scanf("%s",name); for(r=0;r<20;r++)//求出姓名的拼音所对应的整数(关键字) s0+=name[r]; adr=s0%M;//使用哈希函数 d=adr; if(HashList[adr].k==s0)//分3种情况进行判断 printf("\n姓名: %s关键字: %d查找长度为: 1",HashList[d].py,s0); elseif(HashList[adr].k==0) printf("无此记录! "); else {intg=0; do {d=(d+s0%10+1)%M;//伪随机探测再散列法处理冲突 sum=sum+1; if(HashList[d].k==0) {printf("无此记录! "); g=1; } if(HashList[d].k==s0) {printf("\n姓名: %s关键字: %d查找长度为: %d",HashList[d].py,s0,sum); g=1; } }while(g==0); } } (4)显示哈希表 Ø显示哈希表的的格式: \n地址\t关键字\t\t搜索长度\tH(key)\t姓名\n Ø显示哈希表的函数voidDisplay()的: voidDisplay()//显示 {inti; floataverage=0; printf("\n地址\t关键字\t\t搜索长度\tH(key)\t姓名\n");//显示的格式 for(i=0;i<50;i++) {printf("%d",i); printf("\t%d",HashList[i].k); printf("\t\t%d",HashList[i].si); printf("\t\t%d",HashList[i].k%M); printf("\t%s",HashList[i].py); printf("\n"); } for(i=0;i average+=HashList[i].si; average/=NAME_NO; printf("\n平均查找长度: ASL(%d)=%f\n",NAME_NO,average); } (5)主函数设计 voidmain() {charch1; InitNameList(); CreateHashList(); do {printf("D.显示哈希表\nF.查找\nQ.退出\n请选择: "); cin>>&ch1; switch(ch1) { case'D': Display();cout< case'F': FindList();cout< case'Q': exit(0); } cout<<"comeon! (y/n): "; cin>>&ch1; }while(ch1! ='n'); } 3.2.3函数模块 模块调用关系 主函数模块 输出模块 查找模块 哈希表模块 姓名初始化模块 3.2.4程序流程图 本次程序流程图如下 4.调试报告 4.1调试中的问题 经过对哈希表的研究后,即进行程序的设计和编码;将原程序编好后,经过编译,有如下几个问题: Ø在声明了结构体NAME后,最开始结构体内的charname[20]用来存放姓名拼音,最长为20位;经分析,name表示所存姓名拼音的首地址,无需再申明具体的数组长度来存放姓名拼音,这样增加了系统的开销,最后改成char*name,对存放姓名拼音时直接对name赋值,系统直接按照字符数组来存放姓名拼音,而存放长度没有固定。 Ø建立哈希表的函数: voidCreateHashList()中,如果遇到冲突后,在do{}while();语句中,利用伪随机探测再散列法处理冲突,没执行一次就要将记录查找长度的sum增加一次,在这个循环执行完后,即找到一个不冲突的地址来存放姓名拼音,经过自习分析,此时的查找长度需要加1,即将原来的语句HashList[d].si=sum;改成HashList[d].si=sum+1;此时的HashList[d].si才是正确的查找长度。 Ømain函数中的do{}while()语句中,最开始while()语句是: while(a! ='N'||a! ='n')经过分析,在用户需要退出时,不论输入a=N还是a=n,都将继续循环;经过自习思考,最终将while()语句改成: while(a=='Y'||a=='y'),这样就实现了用户的选择。 4.2对设计和编码的讨论和分析 算法采用结构体和数组来存储数据,利用除留余数法得到哈希地址,利用为随机序列法来处理冲突,姓名拼音的关键字为字符串的各个字符所对应的ASCII码相加,所得的整数。 求哈希地址时模为51,哈希表的总长度为50,而实际名字只有30个,因此有20个地址空间被空闲着,这浪费了一定的内存。 算法的时间复杂度为: O(n)。 平均查找长度为: 1.566667 装填因子为: 30/50=0.6 5.程序运行结果 经过对程序错误的修改后,程序执行,经过分析,程序运行结果正确,满足题目要求! 运行结果主要截图如下: Ø程序开始后,初始界面为: Ø选择S后结果为: 结果显示,平均查找长度为1.566667,符合题设要求! Ø选择Y继续后选择F查找 查找成功结果为: 查找失败结果为: 6.经验和体会 6.1感受和体会 《数据结构》这门课程是计算机专业一门基础性学科,重要性可见一斑,学好这门课程对以后人生的发展具有深远的影响。 而数据结构的课程设计便是对学习效果的检验。 数据结构课程设计不仅可以锻炼我们独立思考问题、解决问题的能力,而且可以培养我们的整体性思维的能力;通过课程设计,使我了解了很多数据结构的经典问题和经典算法,加深了对数据结构的再认识,巩固了数据结构的基础性知识,比如: 存储结构、数据查找、哈希表的设计和查找、算法分析等。 哈希表是根据关键码值而直接进行访问的数据结构,它把关键码值通过哈希函数映射到表中一个地址来存储记录,以加快查找的速度。 哈希函数的构造方法有: 直接寻址法、数字分析法、平方取中法、折叠法、随机数法、除留余数法等;对于地址冲突要进行解决,主要解决冲突的的方法有: 开放寻址法(线性探测再散列、二次探测再散列、伪随机探测再散列)、再散列法、链地址法、建立一个公共溢出区等。 查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。 因此,影响产生冲突多少的因素,也就是影响查找效率的因素。 影响产生冲突多少有以下三个因素: 散列函数是否均匀、处理冲突的方法、散列表的装填因子。 通过查找相关资料还了解了著名的hash算法: MD4、MD5、SHA-1及其他。 哈希表的主要用途为: 文件校验、数字签名、鉴权协议等。 这也是对于以后继续研究数据结构所必须了解的知识。 这次课程设计,我明白了对于编写程序,解题的思路尤为重要。 在编写程序之前,如果没有比较清晰的思路,根本不可能编出好的程序。 就算马马虎虎的编出来,程序的逻辑性、健壮性、完善性、合理性也不会很强。 在编程之前,我们应反复研究题目要求,对题目涉及的情况进行比较充分的分析,以便编写出更加符合题意的程序;其次要充分考虑各种临界情况,对一些错误的输入进行处理。 因此在我们编程序之前一定要做好充分的准备,首先要理清自己的思路,然后再将思路分划成几个模块,逐块的写好算法,最后再将所有的模块有机的联系起来,组成一个完整的程序。 在成功通过编译的情况下,对程序运行的结果进行系统的分析,检验其正确性,如果有错误,应立即去分析源程序的逻辑错误,直到得到正确的结果。 在这次课程设计的过程中,我也遇到了很多难题。 在种种的困难中,我明白了在编写程序时要有耐心。 如果你没有耐心,即使再好的算法思路也不会得到很好的表达,特别是在调试的过程中,对于各种各样的错误,要特别的有耐心去自习分析原因,特别是一些基本的语法错误,不能一看到错误很多就乱了阵脚,更不能轻易的放弃,半途而废。 比如在调试中没有定义某些变量的错误、基本的输入输出错误、数据选取不合理的错误、变量名前后不一的错误、函数返回值的错误等等。 其实只要有耐心,你就会发现,在你修改了一个错误之后,其它有的错误也会跟着消失,所以在编译的时候一定要有耐心。 数据结构是一门比较难的课程,需要花很多的时间去不断地练习和实践。 要想把这门课程学好学精并非一件容易的事,特别是一些经典算法,是几十年前人智慧的结晶,对于初学者的理解和应用有一定的难度;但是事在人为,只要肯下功夫,便一定可以学好。 总的来说,这次程序设计让我获益匪浅,相信在以后的学习生活中我也能从中获得启发。 6.2对算法改进的想法 本次哈希表的设计采用的存储结构为顺序存储,这样的存储结构简单易操作,但是必须实现给定存储大小,这样不利于动态操作,在题目允许的情况下,可以采用链式存储结构,从而实现动态存储;对关键字的选取还可以按照各个姓名的字母表的顺序等方式,哈希地址的除留余数法的模还可以是其他的接近表长的素数,解决冲突的伪随机序列取余的模长也可以是其他的接近表长的素数;本次哈希表的总长度为50,而实际只用到了30个,还余下20个空闲地址被白白浪费了,可以在满足题目要求的情况下适当的选取小一点的总表长。 7.哈希表和源程序 7.1哈希表 经过分析,最后得到的哈希表如下: 搜索 长度 地址 存储内容 关键字 H(key) 1 0 (null) 0 0 1 1 wangjiaxin 1072 1 1 2 liuzhenhai 1073 2 4 3 (null) 0 0 1 4 chenjunyan 1075 4 1 5 xuhaiyang 974 5 1 6 wangshichuang 1383 6 1 7 hejie 517 7 1 8 guoqihui 875 8 0 9 0 0 1 10 chenang 724 10 1 11 wangxufeng 1082 11 2 12 wulinfeng 975 6 1 13 yangyiming 1084 13 0 14 0 0 0 15 0 0 1 16 chengkang 934 16 0 17 0 0 1 18 guyuze 681 18 0 19 0 0 2 20 liushuo 777 12 0 21 0 0 1 22 renchao 736 22 0 23 0 0 4 24 yangwenjuan 1191 18 0 25 0 0 1 26 luhaibo 740 26 2 27 chenwan 740 26 3 28 xiehongwei 1079 8 0 29 0 0 0 30 0 0 1 31 yijiabin 847 31 0 32 0 0 0 33 0 0 1 34 wangyuesong 1207 34 1 35 yangchenchen 1259 35 1 36 fanxu 546 36 1 37 shenjin 751 37 0 38 0 0 1 39 caoyandong 1059 39 0 40 0 0 0 41 0 0 0 42 0 0 0 43 0 0 0 44 0 0 2 45 liangfangping 1365 39 3 46 wushengping 1199 26 1 47 puping 659 47 1 48 jiangyong 966 48 2 49 yangchaoqin 1170 48 7.2源程序 整个程序的源代码为: #include #include #include #defineHASH_
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 哈希表 设计