1、数据结构课程设计报告设计题目: 哈希表的设计与实现专 业 通信工程 班 级_学 生_学 号_指导 教师 _起止 时间 XXXXXX 学院2011 年 上 学期2目 录一设计要求-1二数据结构选择与概要设计2.1 数据结构选择-12.2 流程图-2以号码为关键字哈希流程-2以姓名为关键字哈希流程-3添加信息节点流程图-4姓名查找流程图-5号码查询流程图-6三设计算法3.1 建立节点-73.2 哈希函数的定义-73.3 哈希查找-8四测试结果4.1 操作说明-84.2 主菜单截图-94.3 添加记录截图-94.4 散列结果截图-104.5 查找记录截图-104.5 清空记录截图-11五程序源代码及
2、实验心得5.1 源代码-11205.2 实验心得-201一设计要求【问题描述】设计哈希表实现电话号码查询系统。设计程序完成以下要求:【基本要求】:(1)设每个记录有下列数据项:电话号码、用户名、地址;(2)从键盘输入各记录,分别以电话号码和用户名为关键字建立哈希表;(3)采用再哈希法解决冲突;(4)查找并显示给定电话号码的记录;(5)查找并显示给定用户的记录。(6)在哈希函数确定的前提下,尝试各种不同类型冲突吃力方法(至少两种) ,考察平均查找长度思路:(1)对于以号码为关键字的散列函数,是将十一个数字全部相加,然后对 20 求余。得到的数作为地址。对于以用户名为关键字的散列函数,是将所有字母
3、的ASCLL 码值 相加,然后对 20 求余。(2)要添加用户信息,即要有实现添加结点的功能的函数,所以要设计一个必须包括一个输入结点信息、添加结点的函数;(3)要实现查找函数,则必须包括一个查找结点的函数;另外还有一个必不可少的就是运行之后要有一个主菜单,即要设计一个主函数(main()) 。(4)测试数据的选择最后,程序完成后要对程序进行编译调试,执行后要选择数据进行测试,这里选择的测试数据为:1.姓名:郑治华;电话:18772306365;地址:湖北蕲春;2.姓名:蔡翔;电话:18772306205;地址:江苏宿迁;3.姓名:朱利庆;电话:18772307531;地址:湖北阳新;二数据结
4、构选择与概要设计2.1 数据结构选择本设计涉及到的数据结构为:哈希表。要求输入电话号码、用户名、地址三个信息,并要求分别以电话号码和用户名为关键字进行查找,所以本问题要用到两个哈希函数,进行哈希查找。在链地址法中,每个结点对应一个链表结点,它由三个域组成,而由于该程序需要分别用电话号码和用户名为关键字建立哈希表,所以该链表结点它是由四个域组成,链接地址法结点结构如图:name8 num11 address20 next其中 name8和 num11是分别为以电话号码和用户名为关键字域,存放关键字(key) ;address20(data)为结点的数据域,用来存储用户的地址。Next 指针是用来
5、指向下一个结点的地址。22.2 流程图Hash 函数流程图以号码为关键字的 hash 函数流程图取整型 num2赋给 keyi 从 3 开始取numi!=0Key=key+(int) numii+Key=key%20开 始结束3以姓名为关键字的 hash 函数流程图取整型 name0赋给 key2i 从 0 开始取namei不为空Key2+=nameii+Key2=key%20开 始结束4添加信息节点流程图开始申请新的结点 newphone,newname 即新的号码和名字Newname 指向 newphoneNewphone=input()调用 hash()函数拉链法处理冲突利用用户名为关键
6、字插入调用 hash()函数结束5姓名查找流程图开始调用 hash()函数中新结点 q指向 phonekey-nextq 不为空q=q-nextq 不为空输出无记录输出相应记录结束6号码查询流程图开始调用 hash2()函数中新结点 q 指向phonekey-nextq 不为空q=q-nextq 不为空输出无记录输出相应记录结束7三 设计算法3.1 建立节点struct node char name8,address20; char num11; node * next; ; typedef node* pnode; /可以为一个已有的数据类型声明多个别名,这里为该类型声明了两个指针typed
7、ef node* mingzi; node *phone; node *nam; node *a;3.2 哈希函数的定义本程序要设计两个 hash()函数,分别对应电话号码和用户名。对关键字进行模运算,将运算结果所得的余数作为关键字(或结点)的存储地址,方法如下:以电话号码为关键字建立哈希函数 hash(char num11)。以用户名为关键字建立哈希函数 hash2(char name8)。利用强制类型转换,将用户名的每一个字母的 ASCLL 码值相加并且除以 20 后的余数。将计算出来的数作为该结点的地址赋给 key2。void hash(char num11); /以电话号码为关键字建立
8、哈希函数/哈希函数的主旨是将电话号码的十一位数字全部加起来 int i = 3; key=(int)num2; while(numi!=NULL) key+=(int)numi; i+; key=key%20; /利用强制类型转换,将用户名的每一个字母的 ASCLL 码值相加并且除以 20 后的余数 void hash2(char name8); /哈希函数 以用户名为关键字建立哈希函数 int i = 1; key2=(int)name0; while(namei!=NULL) key2+=(int)namei; i+; key2=key2%20; 83.3 哈希查找想要实现查找功能,同样需
9、要两个查找函数,无论以用户名还是以电话号码为关键字,首先,都需要利用 hash 函数来计算出地址。再通过比对,如果是以电话号码为关键字,比较其电话号码是否相同,如果相同则输出该结点的所有信息,如果以用户名为关键字,则比较用户名是否相同,如果相同则输出该结点的所有信息。如果找不到与之对应相同的,则输出“无此记录” 。void find(char num11) ; /在以电话号码为关键字的哈希表中查找用户信息 hash(num); node *q=phonekey-next; while(q!= NULL) if(strcmp(num,q-num)=0) break; q=q-next; if(q
10、) printf(“%s_%s_%sn“,q-name,q-address,q-num);else printf(“无此记录n“); void find2(char name8) ;/ 在以用户名为关键字的哈希表中查找用户信息 hash2(name); node *q=namkey2-next; while(q!= NULL) if(strcmp(name,q-name)=0) break; q=q-next; 四测试结果4.1 操作说明:地址可输入的最大字符数是 20,姓名可输入的最大字符数是 8,电话号码都为 11 位。部分截图:94.2 主菜单记录截图4.3 添加记录截图4.4 散列结果
11、截图104.5 查找记录114.6 清空记录截图五程序源代码及实验心得5.1 源代码#include /输入输出流函数#include “string.h“ /字符串处理函数#include “fstream“ /文件操作函数unsigned int key; /电话号码哈希关键字unsigned int key2; /姓名哈希关键字struct node /建立基本查询信息节点 char name20,address50; char num11; node * next; ; typedef node* pnode; /新建电话信息的指针typedef node* mingzi; /新建姓名
12、信息的指针node *phone; /初始化前电话指针没有具体地址值node *nam; /初始化前姓名指针没有具体地址值/电话号码哈希函数12void hash(char num11) /printf(“在 hash 函数内部执行“);int i = 2; key=(int)num1;while(numi!=NULL) key+=(int)numi; i+; key=key%20;/电话号码再哈希函数void rehash(char num11)int i=1;key=(int)num0;while(numi!=NULL)key+=(int)numi;i+;key=(key+i)%20;vo
13、id clash()/电话号码冲突处理node *q=phonekey-next;while(q-name)!=NULL)key=key+1;q=phonekey-next;/姓名冲突处理void clash2()node *q=namkey2-next;while(q-name)!=NULL)key2=key2+1;q=namkey2-next;13/姓名哈希函数 void hash2(char name20) int i=1; key2=(int)name0; while(namei!=NULL) key2+=(int)namei; i+; key2=key2%20; node* inpu
14、t() /输入节点基本信息 /printf(“成功执行“);node *temp; temp = new node; temp-next=NULL; printf(“输入姓名:n“);scanf(“%s“,printf(“输入地址:n“);scanf(“%s“,printf(“输入电话:n“);scanf(“%s“, return temp; int apend() /添加节点 node *newphone; node *newname; newphone=input(); newname=newphone; newphone-next=NULL; newname-next=NULL; has
15、h(newphone-num);/电话号码冲突处理14clash();hash2(newname-name);printf(“电话号码冲突处理后 key 的值:%dn“,key);/姓名冲突处理clash2();printf(“姓名冲突处理后 key 的值:%dn“,key2);newphone-next = phonekey-next; phonekey-next=newphone; newname-next = namkey2-next; namkey2-next=newname; return 0; void create() /新建节点电话信息 int i; phone=new pno
16、de20; for(i=0;inext=NULL; void create2() /新建节点姓名信息 int i; nam=new mingzi20; for(i=0;inext=NULL; void list() /显示号码列表 int i; node *p;node *q=namkey2-next;if(q= NULL)printf(“n 没有存储信息n“);for(i=0;inext; while(p) printf(“nn|-|n“);printf(“电话:%sn“,p-num); printf(“地址:%sn“,p-address);printf(“姓名:%sn“,p-name);
17、printf(“|-|nnn“);p=p-next; void list2() /显示姓名散列 int i; node *p;node *q=namkey2-next;if(q= NULL)printf(“n 没有存储信息n“);for(i=0;inext; while(p) printf(“nn|-|n“);printf(“姓名:%sn“,p-name); printf(“地址:%sn“,p-address);printf(“电话:%sn“,p-num);void list();printf(“|-|nnn“);p=p-next; void find(char num11) /查找用户信息
18、hash(num);/printf(“key 的值是 %d“,key);/printf(“可以执行 hash 函数“);16node *q=phonekey-next; while(q!= NULL) if(strcmp(num,q-num)=0) break; q=q-next; /printf(“是否进行判断?n“);if(q) /printf(“是,判断成功“);printf(“nn|-|n“);printf(“姓名:%sn“,q-name);printf(“地址:%sn“,q-address);printf(“电话:%sn“,q-num);printf(“|-|nnn“); else
19、printf(“n 无此记录nn“); /电话号码冲突处理后的查找void find01(char num11)hash(num);node *p=phonekey-next;if(p=NULL)printf(“n 无此记录nn“);elsewhile(p!=NULL)if(strcmp(num,p-num)=0)printf(“nn|-|n“);printf(“姓名:%sn“,p-name); printf(“地址:%sn“,p-address);printf(“电话:%sn“,p-num);printf(“|-|nnn“);17if(keynext;void find2(char name
20、20) /查找用户信息 hash2(name); node *q=namkey2-next;while(q!= NULL) if(strcmp(name,q-name)=0) break; q=q-next; if(q) printf(“nn|-|n“);printf(“姓名:%sn“,q-name); printf(“地址:%sn“,q-address);printf(“电话:%sn“,q-num);printf(“|-|nnn“); else printf(“n 无此记录nn“); /姓名冲突处理后的查找void find02(char name20)hash(name);node *q=
21、namkey2-next;if(q= NULL)printf(“n 无此记录nn“);18elsewhile(q!= NULL)if(strcmp(name,q-name)=0)printf(“nn|-|n“);printf(“姓名:%sn“,q-name); printf(“地址:%sn“,q-address);printf(“电话:%sn“,q-num);printf(“|-|nnn“);if(key20)key2=key2-1;q=namkey2-next;/菜单 void menu() printf(“n|-|n“);printf(“|-1.添加记录 -|n“);printf(“|-2
22、.查找记录 -|n“);printf(“|-3.姓名散列 -|n“);printf(“|-4.号码散列 -|n“);printf(“|-5.清空记录 -|n“);printf(“|-6.退出系统 -|n“);printf(“|-7.显示已有信息 -|n“);printf(“|-|n“); int main() char num11; char name20; create(); 19create2() ; int sel; while(1) menu();scanf(“%d“,if(sel=2) printf(“9 从号码开始查询n8 从姓名开始查询n“);int b; scanf(“%d“,
23、if(b=9) printf(“请输入电话号码:n“);scanf(“%s“,printf(“n 输出查找的信息:nn“);find01(num); else printf(“请输入姓名:n“);scanf(“%s“,printf(“n 输出查找的信息:nn“); find02(name); if(sel=3) printf(“姓名散列结果:n“);list2(); if(sel=1) printf(“请输入要添加的内容:n“);apend(); 20if(sel=4) printf(“号码散列结果:n“);list(); if(sel=5) printf(“列表已清空:n“);create(
24、); create2(); if(sel=6) return 0;if(sel=7) list2(); return 0; 5.2 实验心得课程设计终于结束了。虽然遇到过很多麻烦,曾经也很无力、烦恼,但是也收获很多,感觉像是一个从无到有的过程,非常的充实。我做的课题是“哈希表问题” 。基本算法课本上都有涉及过,但具体要独立去完成还是很难。我在一边做上机实验时,一边到网上查阅资料翻看书籍,反复尝试,体会的更加深刻。通过本次课程设计对哈希表问题有了一个比较全面的认识和了解。哈希表问题,在存储位置和关键字之间建立对应关系 f,根据对应关系 f找到定值 K。若结构中存在关键字和定值 K 相等的记录,必定在 f(K )的存储位置上,由此可以省去比较过程,直接找到所查记录。哈希表其实不难,课程设计考验的是我们的学习态度,独立思考问题,和解决问题的能力。这是一个难得的锻炼机会!21