散列法的实验研究课程设计报告.docx
《散列法的实验研究课程设计报告.docx》由会员分享,可在线阅读,更多相关《散列法的实验研究课程设计报告.docx(22页珍藏版)》请在冰豆网上搜索。
散列法的实验研究课程设计报告
课程设计报告问题描述:
(1)
散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突
的方法也可以不同。
两者是影响查询算法性能的关键因素。
(2)
程序实现几种典型的散列函数构造方法,并观察,不同的解决冲突方法对
查询性能的影响。
a.需求分析:
散列表(Hashtable,也叫哈希表),是根据关键码值(Keyvalue)而直接进行访问的数据结构。
对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。
具有相同函数值的关键字对该散列函数来说称做同义词。
综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象”作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。
散列表的查找过程基本上和造表过程相同。
一些关键码可通过散列函数转换的地址直接找到,另一些关键码在散列函数得到的地址上产生了冲突,需要按处理冲突的方法进行查找。
对散列表查找效率的量度,依然用平均查找长度来衡量。
查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。
因此,影响产生冲突多少的因素,也就是影响查找效率的因素。
该课程设计要求比较几种哈希函数的构造方法和解决冲突的方法对查询性能的影响。
b.概要设计
该程序实现对哈希函数的构造方法、处理冲突的方法及在哈希表中查找数据的功能。
用线性再散列方法建立哈希表,用代码实现为:
typedefstruct
{
intkey;
intsi;
}HashTable1;
voidCreateHashTable1(HashTable1*H,int*a,intnum)//哈希表线性探测在散列;
{
inti,d,cnt;
for(i=0;i{
H[i].key=0;
H[i].si=0;
}
for(i=0;i{
cnt=1;
d=a[i]%HashSize;
if(H[d].key==0)
{
H[d].key=a[i];
H[d].si=cnt;
}
else
{
do
{
d=(d+1)%HashSize;
cnt++;
}while(H[d].key!
=0);
H[d].key=a[i];
H[d].si=cnt;
}
}
printf("\n线性再探索哈希表已建成!
");
}
用二次探测再散列建立哈希表,代码实现如下:
voidCreateHash3(HashTable3*h,int*a,intnum)//二次探索表
{
inti,p=-1,c,pp;
for(i=0;i{
c=0;
p=a[i]%HashSize;
pp=p;
while(h->elem[pp]!
=NULL)
{
pp=Collision(p,c);
if(pp<0)
{
printf("第%d个记录无法解决冲突\n",i+1);
continue;
}
}
h->elem[pp]=&(a[a[i]]);
h->count++;
printf("第%d个记录冲突次数为%d\n",i+1,c);
}
printf("\n建表完成!
\n此哈希表容量为%d,当前表内存储的记录个数%d.\n",HashSize,h->count);
}
二次探测再散列法解决冲突
intCollision(intp,int&c)
{
inti,q;
i=c/2+1;
while(i{
if(c%2==0)
{
c++;
q=(p+i*i)%HashSize;
if(q>=0)
returnq;
else
i=c/2+1;
}
else
{
q=(p-i*i)%HashSize;
c++;
if(q>=0)returnq;
elsei=c/2+1;
}
}
return(-1);
}
用线性再散列法查找,代码实现如下:
voidSearchHash1(HashTable1*h,intdata)
{
intd;
d=data%HashSize;
if(h[d].key==data)
printf("数字%d的探查次数为:
%d\n",h[d].key,h[d].si);
else
{
do
d=(d+1)%HashSize;
while(h[d].key!
=data&&dif(dprintf("数字%d的探查次数为:
%d\n",h[d].key,h[d].si);
else
printf("没有查找到你所输入的数\n");
}
用二次探测再散列法查找
voidSearchHash2(HashTable2*h[],intdata,intnum)
{
intd;
Node*q;
d=data%num;
q=h[d]->link;
while(q->key!
=data&&q->next!
=NULL)
q=q->next;
if(q->next!
=NULL)
printf("数字%d的查找次数为:
%d\n",q->key,q->next);
else
printf("没有找到你要查找的那个数\n");
}
用链地址法查找,代码实现如下:
voidCreateHashTable2(HashTable2*ht[],int*a,intnum)//哈希表链地址;{
inti,d,cnt;
Node*s,*q;
for(i=0;i{
ht[i]=(HashTable2*)malloc(sizeof(HashTable2));
ht[i]->link=NULL;
}
for(i=0;i{
cnt=1;
s=(Node*)malloc(sizeof(Node));
s->key=a[i];s->next=NULL;
d=a[i]%num;
if(ht[d]->link==NULL)
{
ht[d]->link=s;
s->si=cnt;
}
else
{
q=ht[d]->link;
while(q->next!
=NULL)
{
q=q->next;cnt++;
}
cnt++;
s->si=cnt;
q->next=s;
}
}
}
c.详细设计
(1)程序中结构体的定义
typedefstruct
{
intkey;
intsi;
}HashTable1;
typedefstructnode
{
intkey;
intsi;
structnode*next;
}Node;
typedefstruct
{
Node*link;
}HashTable2;
typedefstruct
{
int*elem[HashSize];
intcount;
intsize;
}HashTable3;
(2)主函数模块
voidmain()
{
intdata;
HashTable1hash1[HashSize];
HashTable2*hash2[HashSize];
HashTable3*ha;
ha=(HashTable3*)malloc(sizeof(HashTable3));
for(inti=0;iha->elem[i]=NULL;
ha->count=0;
ha->size=HashSize;
inta[MaxSize];
while
(1)
{
printf("\n
┏━━━━━━━━━━━━━━━┓");
printf("\n
┃
欢迎使用本系统┃");
printf("\n┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┓");
printf("\n┃★★★★★★散列法的实验研究★★★★★★┃");
printf("\n┃【1】.添加数据信息【2】数据的输出┃");
printf("\n┃【3】.建立哈希表(线性再散列)
printf("\n┃【4】.建立哈希表(二次探测再散列)printf("\n┃【5】.建立哈希表(链地址法)
┃");
┃");
┃");
printf("\n┃【6】.线性再散列法查找┃");
printf("\n┃【7】.二次探测再散列法查找┃");
printf("\n┃【8】.链地址法查找┃");
printf("\n┃【0】.退出程序┃");
printf("\n┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┛");printf("\n");
printf("\n");
printf("请输入一个任务选项>>>");
intx;
scanf("%d",&x);
switch(x)
{
case1:
GetIn(a);break;
case2:
GetOut(a);break;
case3:
CreateHashTable1(hash1,a,num);break;
case4:
CreateHash3(ha,a,num);break;
case5:
CreateHashTable2(hash2,a,num);break;
case6:
printf("请输入你查找的数据:
");scanf("%d",&data);
SearchHash1(hash1,data);break;
case7:
printf("请输入你查找的数据:
");scanf("%d",&data);
SearchHash3(ha,data);break;
case8:
printf("请输入你查找的数据:
");scanf("%d",&data);
SearchHash2(hash2,data,num);break;
case0:
exit(-1);
}
}
}
d.调试分析
(1)程序的关键是掌握文件的相关操作、哈希函数的创建和运用、处理冲突的方法等。
在编程过程中,出现了很多问题,如文件无法正常打开、程序无法运行、添加的头文件错误等。
修改后程序运行正常。
(2)关于散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突的方法也可以不同。
两者是影响查询算法性能的关键因素。
对不同的数采取不同的函数构造方法和处理冲突的方法,需要认真分析和研究。
添加数据信息,运行结果如下图:
数据的输出,运行结果如下图:
用线性再散列方法建立哈希表,运行结果如下图:
用二次探测再散列建立哈希表,运行结果如下图:
用线性再散列法查找,运行结果如下图所示:
用二次探测再散列法查找,运行结果如下图:
用链地址法查找,运行结果如下图:
退出程序,运行结果如下图:
对性能的分析:
查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。
因此,影响产生冲突多少的因素,也就是影响查找效率的因素。
影响产生冲突多少有以下三个因素:
1、散列函数是否均匀;2、处理冲突的方法;3、散列表的装填因子。
散列表的装填因子定义为:
α=填入表中的元素个数/散列表的长度。
α是散列表装满程度的标志因子。
由于表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。
实际上,散列表的平均查找长度是装填因子α的函数,只是不同处理冲突的方法有不同的函数。
(e)课程总结
(1)收获
通过本次课程设计,使我对计算机语言有了更深一层的了解,也使我对算法的运用有了更多的体会,对算法和生活的联系也有了更多的体会。
更进一步了解和熟悉了关于哈希表的创建和运用。
现在,计算机领域,他只向我展现了冰山一角,以后我会继续探索。
好的算法源于我们不断的思考,思考源于我们对梦想的追寻。
(2)心得体会
在这次数据结构设计中遇到了很多实际性的问题,在实际设计中才发现。
书本上理论性的东西在实际应用中还是有一定的出入的。
所以有些问题要不断的更正以前的错误思维。
通过这次设计,我懂得了学习的重要性,了解到理论知识与实践结合的重要意义。
学会了坚持、耐心和努力,这将为自己今后的学习和工作打下牢固的基础。
通过学习,对专业知识了解更多,学会如何把自己平时所学的东西应用到实际中。
-----------------------------------------------------------------------------------------
参考文献:
[1]李云清,杨庆红.数据结构(C语言版).北京:
人民邮电出版社,2004.
[2]严蔚敏,吴伟民.数据结构(C语言版).北京:
清华大学出版.1997.
[3]苏光奎,李春葆.数据结构导学.北京:
清华大学出版.2002.
[4]
周海英,马巧梅,靳雁霞.数据结构与算法设计.北京:
国防工业出版社,
2007.
[5]张海藩.软件工程导论.北京:
清华大学出版社.2003.
[6]互联网
附录:
程序清单
#include
#include
#defineHashSize53
#defineMaxSize20
typedefstruct
{
intkey;
intsi;
}HashTable1;
voidCreateHashTable1(HashTable1*H,int*a,intnum)//哈希表线性探测在散列;
{
inti,d,cnt;
for(i=0;i{
H[i].key=0;
H[i].si=0;
}
for(i=0;i{
cnt=1;
d=a[i]%HashSize;
if(H[d].key==0)
{
H[d].key=a[i];
H[d].si=cnt;
}
else
{
do
{
d=(d+1)%HashSize;
cnt++;
}while(H[d].key!
=0);
H[d].key=a[i];
H[d].si=cnt;
}
}
printf("\n线性再探索哈希表已建成!
");}
voidSearchHash1(HashTable1*h,intdata)
{
intd;
d=data%HashSize;
if(h[d].key==data)
printf("数字%d的探查次数为:
%d\n",h[d].key,h[d].si);
else
{
do
d=(d+1)%HashSize;
while(h[d].key!
=data&&dif(dprintf("数字%d的探查次数为:
%d\n",h[d].key,h[d].si);
else
printf("没有查找到你所输入的数\n");
}
}
typedefstructnode
{
intkey;
intsi;
structnode*next;
}Node;
typedefstruct
{
Node*link;
}HashTable2;
voidCreateHashTable2(HashTable2*ht[],int*a,intnum)//哈希表链地址;{
inti,d,cnt;
Node*s,*q;
for(i=0;i{
ht[i]=(HashTable2*)malloc(sizeof(HashTable2));
ht[i]->link=NULL;
}
for(i=0;i{
cnt=1;
s=(Node*)malloc(sizeof(Node));
s->key=a[i];s->next=NULL;
d=a[i]%num;
if(ht[d]->link==NULL)
{
ht[d]->link=s;
s->si=cnt;
}
else
{
q=ht[d]->link;
while(q->next!
=NULL)
{
q=q->next;cnt++;
}
cnt++;
s->si=cnt;
q->next=s;
}
}
}
voidSearchHash2(HashTable2*h[],intdata,intnum)
{
intd;
Node*q;
d=data%num;
q=h[d]->link;
while(q->key!
=data&&q->next!
=NULL)
q=q->next;
if(q->next!
=NULL)
printf("数字%d的查找次数为:
%d\n",q->key,q->next);else
printf("没有找到你要查找的那个数\n");
}
typedefstruct
{
int*elem[HashSize];
intcount;
intsize;
}HashTable3;
intCollision(intp,int&c)//二次探测再散列法解决冲突
{
inti,q;
i=c/2+1;
while(i{
if(c%2==0)
{
c++;
q=(p+i*i)%HashSize;
if(q>=0)
returnq;
else
i=c/2+1;
}
else
{
q=(p-i*i)%HashSize;
c++;
if(q>=0)returnq;
elsei=c/2+1;
}
}
return(-1);
}
voidCreateHash3(HashTable3*h,int*a,intnum)//二次探索表{
inti,p=-1,c,pp;
for(i=0;i{
c=0;
p=a[i]%HashSize;
pp=p;
while(h->elem[pp]!
=NULL)
{
pp=Collision(p,c);
if(pp<0)
{
printf("第%d个记录无法解决冲突\n",i+1);
continue;
}
}
h->elem[pp]=&(a[a[i]]);
h->count++;
printf("第%d个记录冲突次数为%d\n",i+1,c);
}
printf("\n建表完成!
\n此哈希表容量为%d,当前表内存储的记录个数%d.\n",HashSize,h->count);
}
voidSearchHash3(HashTable3*h,intdata)//哈希表二次探索再散列查找{
intc=0,p,pp;
p=data%HashSize;
pp=p;
while((h->elem[pp]!
=NULL)&&(*(h->elem[pp])!
=data))
pp=Collision(p,c);
if((h->elem[pp]!
=NULL)&&(*(h->elem[pp])==data))
printf("\n查找成功!
\n查找冲突次数为%d:
",c);
else
printf("\n没有查到此数!
\n");
}
intnum;
voidGetIn(int*a)
{
printf("输入添加的个数:
");
scanf("%d",&num);
for(inti=0;iscanf("%d",&a[i]);
printf("数据已经输入完毕!
\n");
}
voidGetOut(int*a)
{
printf("你所输入的数据:
");
for(inti=0;iprintf("%d,",a[i]);
printf("\n输出已完毕!
");
}
voidmain()
{
intdata;
HashTable1hash1[HashSize];
HashTable2*hash2[HashSize];
HashTable3*ha;
ha=(HashTable3*)malloc(sizeof(HashTable3));
for(inti=0;iha->elem[i]=NULL;
ha->count=0;
ha->size=HashSize;
inta[MaxSize];
while
(1)
{
printf("\n
┏━━━━━━━━━━━━━━━┓");
printf("\n
┃
欢迎使用本系统┃");
printf("\n┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┓");
printf("\n┃★★★★★★散列法的实验研究★★★★★★┃");
printf("\n┃【1】.添加数据信息【2】数据的输出┃");
printf("\n┃【3】.建立哈希表(线性再散列)
printf("\n┃【4】.建立哈希表(二次探测再散列)printf("\n┃【5】.建立哈希表(链地址法)
┃");
┃");
┃");
printf("\n┃【6】.线性再散列法查找┃");
printf("\n┃【7】.二次探测再散列法查找┃");
printf("\n┃【8】.链地址法查找┃");
printf("\n┃【0】.退出程序┃");
printf("\n┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┛");printf("\n");
printf("\n");
printf("请输入一个任务选项>>>");
intx;
scanf("%d",&x);
switch(x)
{
case1:
GetIn(a);break;
case2:
GetOut(a);break;
case3:
CreateHashTable1(hash1,a,num);break;
case4:
CreateHash3(ha,a,num);break;
case5:
CreateHashTable2(hash2,a,num);break;
case6:
printf("请输入你查找的数据:
");
scanf("%d",&data);
SearchHash1(hash1,data);break;
case7:
printf("请输入你查找的数据:
");
scanf("%d",&data);
SearchHash3(ha,data);break;
case8:
printf("请输入你查找的数据:
");
scanf("%