哈希表的设计与实现-数据结构与算法课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
合肥学院
计算机科学与技术系
课程设计报告
2009 ~2010 学年第二学期
课程数据结构与算法
课程设计名称哈希表的设计与实现
学生姓名王东东
学号0804012030
专业班级08计本(2)
指导教师王昆仑、李贯虹
2010 年5 月
课程设计目的
“数据结构与算法课程设计”是计算机科学与技术专业学生的集中实践性环节之一,
是学习“数据结构与算法”理论和实验课程后进行的一次全面的综合练习。其目的是要达到
理论与实际应用相结合,提高学生组织数据及编写程序的能力,使学生能够根据问题要求和
数据对象的特性,学会数据组织的方法,把现实世界中的实际问题在计算机内部表示出来并
用软件解决问题,培养良好的程序设计技能。
一、问题分析和任务定义
1、问题分析
要完成如下要求:设计哈希表实现电话号码查询系统。
实现本程序需要解决以下几个问题:
(1)如何定义一个包括电话号码、用户名、地址的节点。
(2)如何以电话号码和用户名为关键字建立哈希表。
(3)用什么方法解决冲突。
(4)如何查找并显示给定电话号码的记录。
(5)如何查找并显示给定用户名的记录。
2 任务定义
1、由问题分析知,本设计要求分别以电话号码和用户名为关键字建立哈希表,z在此基
础上实现查找功能。本实验是要我们分析怎么样很好的解决散列问题,从而建立一比较合理
的哈希表。由于长度无法确定,并且如果采用线性探测法散列算法,删除结点会引起“信息
丢失”的问题。所以采用链地址法散列算法。采用链地址法,当出现同义词冲突时,可以使
用链表结构把同义词链接在一起,即同义词的存储地址不是散列表中其他的空地址。
根据问题分析,我们可以定义有3个域的节点,这三个域分别为电话号码char num[30],姓名char name[30],地址char address[30]。这种类型的每个节点对应链表中的每个节点,其中电话号码和姓名可分别作关键字实现哈希表的创建。
二、数据结构的选择和概要设计
1、数据结构的选择
数据结构:散列结构。
散列结构是使用散列函数建立数据结点关键词与存储地址之间的对应关系,并提供多
种当数据结点存储地址发生“冲突”时的处理方法而建立的一种数据结构。
散列结构基本思想,是以所需存储的结点中的关键词作为自变量,通过某种确定的函
数H(称作散列函数或者哈希函数)进行计算,把求出的函数值作为该结点的存储地址,并
将该结点或结点地址的关键字存储在这个地址中。
散列结构法(简称散列法)通过在结点的存储地址和关键字之间建立某种确定的函数
关系H,使得每个结点(或关键字)都有一个唯一的存储地址相对应。
当需要查找某一指定关键词的结点时,可以很方便地根据待查关键字K计算出对应的“映像”H(K),即结点的存储地址。从而一次存取便能得到待查结点,不再需要进行若干次的
比较运算,而可以通过关键词直接计算出该结点的所在位置。
2、概要设计
(1)、哈希表的定义
结点的数据类型:
struct node //定义姓名地址电话号码
{
char name[30];
char address[30];
char num[30];
node * next;
}; ElemNode;
(2)、哈希地址的计算
以姓名为关键字的哈希地址计算:从取得的姓名第二个字母开始,取ASCII码累加,对30求余得所求哈希地址
以电话号码为关键字的哈希地址计算:从号码第二位开始,将所有号码累加之后对30求模得哈希地址
(3)、拉链法
链地址法:在散表结构存放在指针指向的单元中。链地址法在解决冲突时,使用链表结构把同义词链接在一起,即同义词的存储地址不是散列表中其他的空地址。
采用C语言定义如下:
#define Max_length 100
Typedef struct{
int key;
ElemType data;
ElemNode *next;
}ElemNode;
Typedef struct{
ElemNode *first;
}ElemHeader,HashTable[Max_length];
所有的同义词构成一个单链表,再由一个表头节点指向这个单链表的第一个节点。这些镖头节点组成一个一维数组,即散列表。数组元素的下标对应由散列函数求出的散列地址。
拉链法处理冲突的散列表结构
1
5
8
(4)链地址法查找结点的算法思想
a、根据查找节点的关键字算出哈希地址
b、在散列地址所指向的单链表中依次寻找节点
c、如果找到,输出节点的信息;否则提示没有找到
三、详细设计和编码主流程图。
以号码为关键字的Hash()函数流程图
以姓名为关键字的Hash()函数流程图
添加结点信息流程图:
编码
1、建立节点
struct node //定义姓名地址电话号码
{
char name[30];
char address[30];
char num[30];
node * next;
};
typedef node* pnode; //声明了已有数据类型的两个指针变量
typedef node* mingzi;
node **phone;
node **nam;
2、定义哈希函数
这里我们需要定义两个哈希函数,一个以电话号码为关键字,另一个以姓名ASCII之和求模之后的值为关键字。主要方法为将电话号码从第二位开始逐一累加并将所得结果对30求模得哈希地址;第二种则是将姓名字符进行强制类型转换之后得ASCII码相加对30求模得哈希地址。
=============================求哈希地址源代码========================== void hash(char num[30]) //哈希函数
//将运算的结果所得的余数作为节点的存储地址
{
int i = 1;
key=(int)num[0];
while(num[i]!=NULL)
{
key+=(int)num[i];
i++;
}
key=key%30;
}
void hash2(char name[30]) //哈希函数
//将运算的结果所得的余数作为节点的存储地址
{
int i = 1;
key2=(int)name[0];
while(name[i]!=NULL)
{
key2+=(int)name[i];
i++;