数据结构报告——散列表、哈希表
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数
据
结
构
实
验
报
告
班级:姓名:学号:时间:
一、题目
散列表的设计
二、要求
1、问题描述
针对某个集体中人名设计一个散列表,使得平均查找长度不超过R,并完成相应的建表和查表程序。
2、基本要求
假设人名为中国人姓名的汉语拼音形式,待填入散列表的人名共有30个,取平均查找长度上限为2。
散列函数用除留余数法构造,用伪随机探测再散列法处理冲突
3、测试数据
取读者周围较熟悉的30人的姓名。
4、实现提示
如果随机函数自行构造,则应首先调整好随机函数,使其发布均匀。
人名的长度不超过20个字符。
可先对过长的人名作折叠处理。
三、设计思想
1、散列函数的构造方法:
散列列函数的构造方法有四种:平方取中法、除余法、相乘取整法、随机数法。
这里用了除余法,该方法是最为简单常用的一种方法。
它是以表长m来除关键字,取其余数作为散列地址,即 h(key)=key%m
该方法的关键是选取m。
选取的m应使得散列函数值尽可能与关键字的各位相关。
m最好为素数。
【例】若选m是关键字的基数的幂次,则就等于是选择关键字的最后若干位数字作为地址,而与高位无关。
于是高位不同而低位相同的关键字均互为同义词。
【例】若关键字是十进制整数,其基为10,则当m=100时,159,259,359,…,等均互为同义词。
2、冲突的处理:
(1)冲突
两个不同的关键字,由于散列函数值相同,因而被映射到同一表位置上。
该现象称为冲突(Collision)或碰撞。
发生冲突的两个关键字称为该散列函数的同义词(Synonym)。
(2)安全避免冲突的条件
最理想的解决冲突的方法是安全避免冲突。
要做到这一点必须满足两个条件:
①其一是|U|≤m
②其二是选择合适的散列函数。
这只适用于|U|较小,且关键字均事先已知的情况,此时经过精心设计散列函数h有可能完全避免冲突。
(3)冲突不可能完全避免
通常情况下,h是一个压缩映像。
虽然|K|≤m,但|U|> m,故无论怎样设计h,也不可能完全避免冲突。
因此,只能在设计h时尽可能使冲突最少。
同时还需要确定解决冲突的方法,使发生冲突的同义词能够存储到表中。
(4)影响冲突的因素
冲突的频繁程度除了与h相关外,还与表的填满程度相关。
设m和n分别表示表长和表中填人的结点数,则将α=n/m定义为散列表的装填因子(Load Factor)。
α越大,表越满,冲突的机会也越大。
通常取α≤1。
(5)冲突处理
对不同的关键字可能得到同一个哈希地址即key1≠key2,而f(key1)=f(key2)。
因此,在建造哈希表时不仅要设定一个好的哈希函数,而且要设定一种处理冲突的方法。
用伪随机探测法。
求下一个开放地址的公式为:Hi = (H(k)+di) MOD m
Di=伪随机数序列;
3、相应的数据结构:
1)、对哈希表的操作
InitNameList()
操作结果:姓名(结构体数组)初始化
CreateHashList()
操作结果:建立哈希表
FindList()
操作结果:在哈希表中查找
Display()
操作结果:显示哈希表
2)、主程序
int main()
{
初始化;
InitNameList();CreateHashList();
do {
接受命令;
处理命令;
}while(“命令”=“退出”);return 0;
}
3 )、本程序包含的模块
1)初始化操作,结构体定义;2)姓名结构体建立模块;
3)建立哈希表模块;
4)查找模块;
5)显示哈希表模块;
4)主程序模块
四、结构图
五、流程图
注①:——散列表设计——
a.显示散列表
b.查找
c.退出
请选择:
六、测试
1.本程序运行环境为C++,生成的可执行文件为a.exe;
该可执行文件的执行环境为DOS。
用户进入演示程序后的界面为:
2.测试结果
输入:a
输出:散列表
输入:b
输入:lilei
输出:无此记录!
输入:chenlinsha
输出:姓名:chenlinsha 关键字:1053 查找长度:1
七、程序清单
#include<iostream>
#include<string>
using namespace std;
#define HASH_LENGTH 50
#define M 47
#define NAME_NO 30
typedef struct
{ char *xm;
int k;
}NAME;
NAME NameList[HASH_LENGTH];
typedef struct
{ char *xm;
int k;
int si;
}HASH;
HASH HashList[HASH_LENGTH];
void InitNameList()
{ char *f;
int r,s0,i;
for (i=0; i<HASH_LENGTH; i++)
{
NameList[i].xm = new char[64];
NameList[i].xm[0] = 0;
}
strcpy(NameList[0].xm, "yingjun");
strcpy(NameList[1].xm, "shengjiayan");
strcpy(NameList[2].xm, "jiangxiya");
strcpy(NameList[3].xm, "caihaipou");
strcpy(NameList[4].xm, "shengwenbing");
strcpy(NameList[5].xm, "chenlinsha");
strcpy(NameList[6].xm, "yangqifan");
strcpy(NameList[7].xm, "zhanglei");
strcpy(NameList[8].xm, "xujie");
strcpy(NameList[9].xm, "chencao");
strcpy(NameList[10].xm, "fangshongwei");
strcpy(NameList[11].xm, "hexiaobing");
strcpy(NameList[12].xm, "xubingbing");
strcpy(NameList[13].xm, "zhangxi");
strcpy(NameList[14].xm, "dinglan");
strcpy(NameList[15].xm, "heliting");
strcpy(NameList[16].xm, "lexiaoying");
strcpy(NameList[17].xm, "rentao");
strcpy(NameList[18].xm, "renxinshi");
strcpy(NameList[19].xm, "zhangjinjun");
strcpy(NameList[20].xm, "lidan");
strcpy(NameList[21].xm, "louwangyue");
strcpy(NameList[22].xm, "zhuangjianjun");
strcpy(NameList[23].xm, "lintingting");
strcpy(NameList[24].xm, "weili");
strcpy(NameList[25].xm, "gaochun");
strcpy(NameList[26].xm, "huangfeixiang");
strcpy(NameList[27].xm, "wangjiangjie");
strcpy(NameList[28].xm, "zhaojuntao");
strcpy(NameList[29].xm, "wangchenli");
for(i=0;i<NAME_NO;i++)
{
s0=0;
f=NameList[i].xm;
for(r=0;*(f+r)!='\0';r++)
s0=*(f+r)+s0;
NameList[i].k=s0;
}
}
void CreateHashList()
{
int i;
for(i=0; i<HASH_LENGTH;i++)
{
HashList[i].xm=new char[64];
HashList[i].xm[0] = 0;
HashList[i].k=0;
HashList[i].si=0;
}
for(i=0;i<HASH_LENGTH;i++)
{
int sum=0;
int adr=(NameList[i].k)%M;
int d=adr;
if(HashList[adr].si==0)
{
HashList[adr].k=NameList[i].k;
HashList[adr].xm=NameList[i].xm;
HashList[adr].si=1;
}
else
{
while (HashList[d].k!=0)
{
d=(d+NameList[i].k%10+1)%M;
sum=sum+1;
};
HashList[d].k=NameList[i].k;
HashList[d].xm=NameList[i].xm;
HashList[d].si=sum+1;
}
}
}
void FindList()
{
string name;
int s0=0,r,sum=1,adr,d;
cout<<endl;
cout<<"请输入姓名的拼音:"<<endl;
cin>>name;;
for(r=0;r<20;r++)
s0+=name[r];
adr=s0%M;
d=adr;
if(HashList[adr].k==s0){
cout<<endl<<"姓名:"<<HashList[d].xm<<endl;
cout<<"关键字:"<<s0<<endl;
cout<<"查找长度为: 1"<<endl;}
else if (HashList[adr].k==0)
cout<<"无此记录!"<<endl;
else
{
int g=0;
while(g==0)
{
d=(d+s0%10+1)%M;
sum=sum+1;
if(HashList[d].k==0)
{
cout<<"无此记录!"<<endl;
g=1;
}
if(HashList[d].k==s0)
{
cout<<endl<<"姓名:"<<HashList[d].xm<<endl;
cout<<"关键字:"<<s0<<endl;
cout<<"查找长度为: 1"<<endl;
g=1;
}
};
}
}
void Display()
{
int i;
float average=0;
cout<<"\n地址\t关键字\t\t搜索长度\tH(key)\t 姓名\n";
for(i=0; i<50; i++)
{
cout<<i<<" ";
cout<<"\t"<<HashList[i].k<<" ";
cout<<"\t\t"<<HashList[i].si<<" ";
cout<<"\t\t"<<(HashList[i].k%M)<<" ";
cout<<"\t "<<HashList[i].xm<<" ";
cout<<"\n";
}
for(i=0;i<HASH_LENGTH;i++)
average+=HashList[i].si;
average/=NAME_NO;
cout<<endl;
cout<<"平均查找长度:ASL("<<NAME_NO<<")="<<average<<endl;
- 10 -
cout<<endl;
cout<<"——散列表设计——"<<endl;
cout<<" a.显示散列表"<<endl;
cout<<" b.查找"<<endl;
cout<<" c.退出"<<endl<<endl;
cout<<"请选择:"<<endl;
}
int main()
{
char x;
InitNameList();
CreateHashList ();
cout<<"——散列表设计——"<<endl;
cout<<" a.显示散列表"<<endl;
cout<<" b.查找"<<endl;
cout<<" c.退出"<<endl<<endl;
cout<<"请选择:"<<endl;
while(cin>>x)
{
if(x=='a')
{
Display();
cout<<endl;
}
else if(x=='b')
{
FindList();
cout<<endl;
}
else break;
}
for (int i=0; i<HASH_LENGTH; i++)
{
free(NameList[i].xm);
free(HashList[i].xm);
}
return 0;
}
- 11 -。