散列表的设计与实现.docx

上传人:b****8 文档编号:11177987 上传时间:2023-02-25 格式:DOCX 页数:47 大小:359.30KB
下载 相关 举报
散列表的设计与实现.docx_第1页
第1页 / 共47页
散列表的设计与实现.docx_第2页
第2页 / 共47页
散列表的设计与实现.docx_第3页
第3页 / 共47页
散列表的设计与实现.docx_第4页
第4页 / 共47页
散列表的设计与实现.docx_第5页
第5页 / 共47页
点击查看更多>>
下载资源
资源描述

散列表的设计与实现.docx

《散列表的设计与实现.docx》由会员分享,可在线阅读,更多相关《散列表的设计与实现.docx(47页珍藏版)》请在冰豆网上搜索。

散列表的设计与实现.docx

散列表的设计与实现

 

课程设计题目

散列表的设计与实现

指导教师姓名

年福忠

指导老师职称

学生姓名

贾存福

所属班级

09计算机五班

 

任务要求

【基本要求】

1)设每个记录有下列数据项:

电话号码、用户名、地址;

2)从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表;

3)采用一定的方法解决冲突;

4)查找并显示给定电话号码的记录;

5)查找并显示给定用户名的记录。

【进一步完成内容】

1)系统功能的完善;

2)设计不同的散列函数,比较冲突率;

3)在散列函数确定的前提下,尝试各种不同类型处理冲突的方法,考察平均查找长度的变化。

主要实施步骤

课程设计时间为两周,从本学期的第二周开始:

第二周的星期一至星期三:

题目分析,完成单元数据结构的定义。

第二周的星期四至星期日:

完成通用散列类的设计与编译。

第三周的星期一至星期二:

完成模块功能模块1至功能模块4的设计与编译。

第三周的星期三至星期五:

完成功能模块5至功能模块10的设计与编译。

第三周的星期六至星期日:

将各个模块整合成一个完整的系统,并录入足够的数据进行调试运行。

.

 

 

散列表在现实世界中,有很大的实用价值。

尤其用在查询领域。

不用比较的办法,直接根据所求结点的关键字值KEY找到这个结点,追求更快的速度O

(1),优于任何其它的查找算法。

本次实验采用链地址法解决散列冲突。

只是对空间和时间效率做出的折中选择。

比如开放寻址法中的双重散列在某些情况下,就有比较好的查找效率。

 

 

1引言

随着世界的快速发展,电话的作用也变得相当明显,它也越来越普及了。

也正是因为它的普及,也带来了一些问题,如用户的增多导致电话号码的增多。

如何有效的记录电话号码?

如何快速地查找出自己所需要的电话记录?

因此电话查询系统就在这样的背景下产生了。

纵观现今所有的电话查询系统,形形色色,但操作简单,查询号码准确,占资源少等问题一般都是人们所渴望的。

而要做到这些就必须要有好的算法和数据结构,因为算法与数据结构总是联系在一起,好的算法总是离不开好的数据结构。

所以现在急需人们利用好的算法和好的数据结构创造出好的电话查询系统来解决当前的需要。

1.1课程设计目标

掌握数据结构的基础技术,学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构、存储结构及其相应的算法,应用相关知识设计散列表实现电话号码查找系统。

1.2编程工具(编程环境)介绍

编程工具:

MicrosoftVisualC++

编程环境:

MicrosoftWindowsxp

1.3实施时间及主要实施步骤

第二周的星期一至星期三:

题目分析,完成单元数据结构的定义。

第二周的星期四至星期日:

完成通用散列类的设计与编译。

第三周的星期一至星期二:

完成模块功能模块1至功能模块4的设计与编译。

第三周的星期三至星期五:

完成功能模块5至功能模块10的设计与编译。

第三周的星期六至星期日:

将各个模块整合成一个完整的系统,并录入足够的数据进行调试运行。

2需求分析

设计散列表实现电话号码查找系统。

功能需求,本课程设计是对电话记录进行一些相关的操作,如添加,查找等。

在本程序中主要运用了数组,链表,字符的比较等知识,现把这电话号码查询系统程序的主框架图如下所示:

 

(一)系统模块图

3系统总体设计

本次课程设计在使用散列表时,使用的是链表法解决碰撞,链表法是最简单的解决碰撞的方法,但是非常有用。

之所以选择链表法,还是一个原因就是,从实用角度出发,对空间和时间效率做出的折中选择。

采用开放地址法,无论是线性探测或者二次探测都可能造成群集现象,而双重散列会要求散列表的装填程度比较低的情况下会有比较好的查找效率,容易造成空间的浪费。

再就是哈希函数的选取,我选用了两种哈希函数,一种是BKDRHash函数,无论是在实际效果还是编码实现中,效果都是最突出的。

另一种是ELFHash函数。

可能没有BKDRHash好,但它们都是比较优秀的处理字符串的哈希函数。

本程序包括9个模块,1.一次性添加所有用户信息2.显示一次性添加的所有用户信息3.以用户名建立哈希表(链地址解决冲突)4.以电话号码建立哈希表(链地址解决冲突)5.查找并显示给定用户名的记录6.查找并显示给定电话号码的记录7.添加单条记录到以用户名建立的哈希表中8.添加单条记录到以电话号码建立的哈希表中9.退出程序。

如图

(一)所示。

各个模块的功能描述如下:

(1)密码进入

该模块主要是通过密码进入主菜单密码输入有三次机会,三次输入错误自动结束程序。

(2)主菜单

该模块主要显示菜单信息选择您要进行的步骤。

(3)一次性添加所有用户信息。

该模块包括选择要添加的个数。

先输入个数之后再输入各用户信息。

(4)显示一次性添加的所有用户信息。

该模块主要是读取用户一次性输入的所有用户信息。

(5)以用户名建立哈希表(链地址解决冲突)。

该模块用于以姓名建立哈希表并且用链地址解决冲突。

(6)以电话号码建立哈希表(链地址解决冲突)。

该模块用于以电话号码建立哈希表并且用链地址解决冲突。

(7)查找并显示给定用户名的记录。

该模块以用户名查找信息在执行该步骤之前先执行(3).

(8)查找并显示给定用电话号码的记录。

该模块以用电话号码查找信息在执行该步骤之前先执行(4).

(9)添加单条记录到以用户名建立的哈希表中。

用户输入一条信息存入以用户名建立的哈希表中。

(10)添加单条记录到以电话号码建立的哈希表中

用户输入一条信息存入以电话号码建立的哈希表中。

(11)退出程序

该模块用于退出当前程序。

4数据结构设计

通用类介绍:

note类:

主要用在散列表中作为单条记录的数据结构类型

classnote

{

public:

//散列表中的结点类型

stringkeyPhoneNumber;//电话号码

stringkeyUser;//用户名

stringvalueAddress;//地址

note*next;//指向下一个结点

note();

virtual~note();

};

FunctionCode类:

主要是用来存放哈希函数的公用类

classFunctionCode

{

public:

FunctionCode();

inthashBKD(stringarg);//BKDRHash哈希函数

inthashELF(stringarg);//ELFHash哈希函数

virtual~FunctionCode();

};

 

HashTableTel类:

以电话号码为关键字建立散列表的类

classHashTableTel

{

public:

FunctionCodecode;//含哈希函数

note*table[100];//链数组

HashTableTel();

voidput(stringkeyPhoneNumber,stringuser,stringname);//存储记录,通过散列表结构

voidget(stringkeyPhoneNumber);//获取相应记录

virtual~HashTableTel();

};

HashTableUser:

以用户名为关键字建立散列表的通用类

classHashTableUser

{

public:

FunctionCodecode;//含哈希函数

note*table[100];//链数组

HashTableUser();

voidput(stringkeyUser,stringtel,stringname);//存储记录,通过散列表结构

voidget(stringkeyUser);//获取相应记录

virtual~HashTableUser();

};

main.cpp:

程序的入口文件介绍

设置头文件全局变量

#include

#include

#include

#include

#include

#include"HashTableTel.h"

#include"HashTableUser.h"

/**限制存储最大的记录条数*/

#defineMAXSIZE200

//以电话号码为关键字建立散列表的类

HashTableTelhashTel;

//以用户名为关键字建立散列表的类

HashTableUserhashUser;

//初始化的最大记录数

Notenote[MAXSIZE];

//一条记录,电话号码,用户名,地址

stringtelephone,user,address;

//存储实际的记录条数intcount=0;

定义结构体

//存储输入记录的结构定义

typedefstruct{

stringuserName;

stringtelephone;

stringaddress;

}Note;

函数功能描述

1、access()

密码进入系统

2、add()

键盘一次性添加所有用户信息

3、putall()

显示一次性添加的所有用户信息

4、createUser()

以用户名建立哈希表

5、createTel()

以电话号码建立哈希表

6、searchUser()

查找并显示给定用户名的记录

7、searchTel()

查找并显示给定电话号码的记录

8、AddsingleUser()

添加单条记录到以用户名建立的哈希表中

9、AddsingleTel()

添加单条记录到以电话号码建立的哈希表中

5详细设计与实现

散列表实现的电话查找系统。

各功能模块的详细介绍。

5.1功能模块1详细设计

5.1.1详细设计

模块名称:

密码登录验证

功能说明:

该模块主要是通过密码进入主菜单密码输入有三次机会,三次输入错误自动结束程序。

输入参数:

密码为任一字符串。

输出:

密码正确提示进入系统。

不正确提示错误。

5.1.2界面设计及测试结果

 

5.2功能模块2详细设计

5.2.1详细设计

模块名称:

一次性添加所有用户信息

功能说明:

该模块包括选择要添加的个数。

先输入个数之后再输入各用户信息。

输入参数:

依次为:

用户名,电话号码,地址。

各个参数都是字符串类型。

5.2.2界面设计及测试结果

5.3功能模块3详细设计

5.3.1详细设计

模块名称:

显示一次性添加的所有用户信息

功能说明:

该模块主要是读取用户一次性输入的所有用户信息。

输出:

按用户名,电话号码,地址的顺序显示一行记录。

输出各条记录。

5.3.2界面设计及测试结果

5.4功能模块4详细设计

5.4.1详细设计

模块名称:

以用户名建立哈希表(链地址解决冲突)

功能说明:

该模块用于以姓名建立哈希表并且用链地址解决冲突。

输入参数:

按用户名,电话号码,地址的依次顺序在记录数组中提到。

各个参数都为字符串类型。

输出:

字符串消息提示。

所调用其他功能构件及被调用的其他功能构件:

我们调用了hashUser类(以用户名建立散列表的哈希类)的put方法,逐条放入记录建立散列表。

5.4.2算法流程

/*

*ELFHash哈希函数

*@paramarg关键字

*/

intFunctionCode:

:

hashELF(stringarg){

constchar*str=arg.c_str();

unsignedinthash=0;

unsignedintx=0;

while(*str)

{hash=(hash<<4)+(*str++);

if((x=hash&0xF0000000L)!

=0)

{

hash^=(x>>24);

hash&=~x;}

}

return(hash&0x7FFFFFFF)%100;

}

5.4.3界面设计及测试结果

5.5功能模块5详细设计

5.5.1详细设计

模块名称:

以电话号码建立哈希表(链地址解决冲突)。

功能说明:

该模块用于以电话号码建立哈希表并且用链地址解决冲突。

输入参数:

按电话号码,用户名,地址的依次顺序在记录数组中提到。

各个参数都为字符串类型。

输出:

字符串消息提示。

所调用其他功能构件及被调用的其他功能构件:

我们调用了hashTel类(以电话号码建立散列表的哈希类)的put方法,逐条放入记录建立散列表。

5.5.2算法流程

/*

*BKDRHash哈希函数

*无论是在实际效果还是编码实现中,效果都是最突出的。

*@paramarg关键字

*/

intFunctionCode:

:

hashBKD(stringarg){

constchar*str=arg.c_str();

unsignedintseed=131;//31131131313131131313etc..

unsignedinthash=0;

while(*str)

{

hash=hash*seed+(*str++);

}

return(hash&0x7FFFFFFF)%100;

}

5.5.3界面设计及测试结果

5.6功能模块6详细设计

5.6.1详细设计

模块名称:

查找并显示给定用户名的记录

功能说明:

该模块以用户名查找信息在执行该步骤之前先执行(3).

输入参数:

用户名,类型为字符串。

输出:

以该用户名为关键字找到的相应记录。

所调用其他功能构件及被调用的其他功能构件:

我们调用了HashTableUser类(以用户名建立散列表的哈希类)的get方法,在散列表中获取相应的记录。

5.6.2算法流程

/*

*ELFHash哈希函数

*@paramarg关键字

*/

intFunctionCode:

:

hashELF(stringarg){

constchar*str=arg.c_str();

unsignedinthash=0;

unsignedintx=0;

while(*str)

{hash=(hash<<4)+(*str++);

if((x=hash&0xF0000000L)!

=0)

{

hash^=(x>>24);

hash&=~x;}

}

return(hash&0x7FFFFFFF)%100;

}

5.6.3界面设计及测试结果

5.7功能模块7详细设计

5.7.1详细设计

模块名称:

查找并显示给定电话号码的记录

功能说明:

该模块以用户名查找信息在执行该步骤之前先执行(4).

输入参数:

电话号码,类型为字符串。

输出:

以该电话号码为关键字找到的相应记录。

所调用其他功能构件及被调用的其他功能构件:

我们调用了HashTableTel类(以电话号码建立散列表的哈希类)的get方法,在散列表中获取相应的记录。

5.7.2算法流程

/*

*BKDRHash哈希函数

*无论是在实际效果还是编码实现中,效果都是最突出的。

*@paramarg关键字

*/

intFunctionCode:

:

hashBKD(stringarg){

constchar*str=arg.c_str();

unsignedintseed=131;//31131131313131131313etc..

unsignedinthash=0;

while(*str)

{

hash=hash*seed+(*str++);

}

return(hash&0x7FFFFFFF)%100;

}

5.7.3界面设计及测试结果

5.8功能模块8详细设计

5.8.1详细设计

模块名称:

添加单条记录到以用户名建立的哈希表中。

功能说明:

用户输入一条信息存入以用户名建立的哈希表中。

输入参数:

按用户名,电话号码,地址的依次顺序在记录数组中提到。

各个参数都为字符串类型。

输出:

字符串消息提示。

所调用其他功能构件及被调用的其他功能构件:

我们调用了hashUser类(以用户名建立散列表的哈希类)的put方法,放入记录。

5.8.2算法流程

/*

*ELFHash哈希函数

*@paramarg关键字

*/

intFunctionCode:

:

hashELF(stringarg){

constchar*str=arg.c_str();

unsignedinthash=0;

unsignedintx=0;

while(*str)

{hash=(hash<<4)+(*str++);

if((x=hash&0xF0000000L)!

=0)

{

hash^=(x>>24);

hash&=~x;}

}

return(hash&0x7FFFFFFF)%100;

}

5.8.3界面设计及测试结果

5.9功能模块9详细设计

5.9.1详细设计

模块名称:

添加单条记录到以电话号码建立的哈希表中。

功能说明:

用户输入一条信息存入以电话号码建立的哈希表中。

输入参数:

按电话号码,用户名,地址的依次顺序在记录数组中提到。

各个参数都为字符串类型。

输出:

字符串消息提示。

所调用其他功能构件及被调用的其他功能构件:

我们调用了hashTel类(以电话号码建立散列表的哈希类)的put方法,放入记录。

5.9.2算法流程

/*

*BKDRHash哈希函数

*无论是在实际效果还是编码实现中,效果都是最突出的。

*@paramarg关键字

*/

intFunctionCode:

:

hashBKD(stringarg){

constchar*str=arg.c_str();

unsignedintseed=131;//31131131313131131313etc..

unsignedinthash=0;

while(*str)

{

hash=hash*seed+(*str++);

}

return(hash&0x7FFFFFFF)%100;

}

5.9.3界面设计及测试结果

5.10功能模块10详细设计

5.10.1详细设计

模块名称:

退出程序

功能说明:

该模块用于退出当前程序。

输入:

任一字符。

输出:

字符串提示,退出程序。

5.10.2界面设计及测试结果

6结论

●散列的效率是很高的

无论是链表法还是开放寻址法,它的运行时间都是常数,当然这取决于装载因子。

实际上散列就是用空间来换取查找的速度。

散列的另外一层意义就是通过关键字散列后的值作为数组索引查找。

●散列函数很重要

理论上,全域散列的一致性比较好.

●链接法和开放寻址法的对比

链表法比较适用于空间要求比较严格,简单实用。

而开放寻址法的探查方法很讲究,线性查找和二次查找都会导致不同程度的群集,所以基本上不用。

最好还是用双重散列,它的探查序列可以达到m的二次方种,比线性探查和二次探查的探查序列可能性要高得多。

本次课程设计,我并没有给出测试用例的分析,也没有用多种方式去实现解决冲突。

这些都是不足的地方。

希望以后能找到比较好的散列函数,并写出比较好的测试用例。

实现不用冲突解决方案的对比。

 

7参考文献

1)《数据结构》,严慧敏等著,2004年,清华大学出版社

2)java的API类

3)XX搜索

4)C++程序设计教程(第二版)钱能著清华大学出版社

 

8附录

程序文档:

1)类的头文件集:

-------------------------------------------FunctionCode.h

#include

#include

usingnamespacestd;

classFunctionCode

{

public:

FunctionCode();

inthashBKD(stringarg);//哈希函数1

inthashELF(stringarg);//哈希函数2

virtual~FunctionCode();

};

 

-----------------------------------------HashTableTel.h

#include

#include

#include"note.h"

#include"FunctionCode.h"

#include

usingnamespacestd;

//以电话号码为关键字建立哈希表的通用类

classHashTableTel

{

public:

FunctionCodecode;//含哈希函数

note*table[100];//链数组

HashTableTel();

voidput(stringkeyPhoneNumber,stringuser,stringname);//存储记录,通过散列表结构

voidget(stringkeyPhoneNumber);//获取相应记录

virtual~HashTableTel();

};

----------------------------------------------HashTableUser.h

#include

#include

#include"note.h"

#include"FunctionCode.h"

usingnamespacestd;

 

//以用户名为关键字建立哈希表的通用类

classHashTableUser

{

public:

FunctionCodecode;//含哈希函数

note*table[100];//链数组

HashTableUser();

voidput(stringkeyUser,stringtel,stringname);//存储记录,通过散列表结构

voidget(stringkeyUser);//获取相应记录

virtual~HashTableU

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 环境科学食品科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1