哈希表数据结构课设.docx
《哈希表数据结构课设.docx》由会员分享,可在线阅读,更多相关《哈希表数据结构课设.docx(24页珍藏版)》请在冰豆网上搜索。
哈希表数据结构课设
洛阳理工学院
课程设计说明书
课程名称数据结构
设计课题哈希表的设计与实现
专业
班级
学号
姓名
完成日期2
课程设计任务书
设计题目:
哈希表的设计与实现
设计内容与要求:
设计哈希表实现电话号码查询系统。
[基本要求]
1、设每个记录有下列数据项:
电话号码、用户名、地址;
2、从键盘输入各记录,分别以电话号码和用户名为关键字建立哈希表;
3、采用再哈希法解决冲突;
4、查找并显示给定电话号码的记录;
5、查找并显示给定用户名的记录。
6、在哈希函数确定的前提下,考察平均查找长度的变化。
指导教师:
2014年
课程设计评语
成绩:
指导教师:
年月日
【问题描述】
如何设计一个结构体数组使该数组中每个元素包含电话号码、用户名、地址。
如何分别以电话号码和用户名为关键字建立哈希表。
如何利用线性探测再散列法解决冲突。
如何实现用哈希法查找并显示给定电话号码的记录。
如何查找并显示给定用户的记录。
手工计算查找不成功的平均查找长度。
【基本要求】
设计哈希表实现电话号码查询系统。
设计程序完成以下要求:
(1)、设每个记录有下列数据项:
电话号码、用户名、地址;
(2)、从键盘输入各记录,分别以电话号码和用户名为关键字建立哈希表;(3)、采用再哈希法解决冲突
(4)、查找并显示给定电话号码的记录;
(5)、查找并显示给定用户的记录。
(6)、在哈希函数确定的前提下,考察平均查找长度的变化。
【测试数据】
1.用户名:
weiguo,号码:
123,地址:
gansu
2.用户名:
zhangkui,号码:
321,地址:
shanxi
【算法思想】
进入主函数,
用户输入1:
输入哈希表元素,
然后再选择2或者3按照用户名或者电话号码散列,在这下面又有分支语句选择解决冲突的办法,用线性探测再散列还是再哈希法。
生成哈希表之后,选择查找操作3分别以用户名和电话号码为关键字进行查找。
最后,输出查找不成功的平均查找长度。
在本程序当中用了两种解决冲突的办法,分别是线性探测再散列和再哈希法。
哈希函数构造方法是,除留余数法。
具体流程图1所示:
图1具体流程图
【模块划分】
本程序在菜单选项下包含六个子模块,如图2所示
图2模块划分
【数据结构】
本设计涉及到的数据结构为:
哈希表。
要求输入电话号码、用户名、地址三个信息,并要求分别以电话号码和用户名为关键字进行查找,所以本问题要用到两个哈希函数,进行哈希查找。
/*哈希表结构体*/
typedefstruct
{
charname[20];//用户名
charphone[20];//电话
charadd[30];//地址
}Record;
RecordInf[M];//全局变量
RecordH[M];//全局变量
【测试情况】
1.运行程序,显示主菜单并选择选项1来创建哈希表
2.执行选项1,输入元素内容
3.执行选项2,按用户名散列创建哈希表
4.执行选项3,按号码散列创建哈希表
5.执行选项4,按用户名查找
6.执行选项4,按号码查找
7.执行选项5,输出查找不成功的平均查找长度
【心得】
【源程序】
/*****电话号码查询系统*****/
#include
#include
#include
#defineM10
#defineNULLKEY"\0"
/*哈希表结构体*/
typedefstruct
{
charname[20];//用户名
charphone[20];//电话
charadd[20];//地址
}Record;
RecordInf[M];//定义辅助数组为全局变量
RecordH[M];//定义哈希表为全局变量
/*菜单函数*/
intmenu()
{
intm;
system("cls");
system("color0a");
printf("\t\t************电话号码查询系统*************\n");
printf("\n");
printf("\t\t______________主菜单_______________\n");
printf("\t\t|1.哈希表的创建|\n");
printf("\t\t|2.按用户名散列|\n");
printf("\t\t|3.按号码散列|\n");
printf("\t\t|4.查找操作|\n");
printf("\t\t|5.平均查找长度|\n");
printf("\t\t|0.退出程序|\n");
printf("\t\t-----------------------------------------\n");
printf("\n");
printf("\t\t\t请输入您的选项<0-5>:
\n");
scanf("%d",&m);
return(m);
}
//创建辅助数组
intCreate(RecordH[M])
{
inti;
charsign;
for(i=0;i<10;i++)//初始化哈希表
{
strcpy(H[i].add,"\0");
strcpy(H[i].phone,"\0");
strcpy(H[i].name,"\0");
}
i=0;
while(sign!
='n'&&sign!
='N')
{
printf("请输入名字\n");
scanf("%s",Inf[i].name);
printf("请输入号码\n");
scanf("%s",Inf[i].phone);
printf("请输入地址\n");
scanf("%s",Inf[i].add);
printf("\t\t\t还需要继续输入吗?
(Y/N)");
scanf("\t\t\t%c",&sign);
i++;
}
returni;
}
//以用户名为关键字的哈希函数
intHash_name(charname[20])
{
inti=0;
inta=0;
while(name[i]!
='\0')
{
a=a+name[i];
i++;
}
a=a%7;//对小于哈希表的最大素数求余,此处哈希表长为10,对7求余
return(a);
}
//再哈希
intname_again(charname[20])
{
inti,h;
h=(int)name[1];
for(i=2;i<20;i++)
h=h+(int)name[i];
h=h%7;
returnh;
}
//以用户名为关键字创建哈希表
voidcreat_name(RecordInf[M],intm,RecordH[M])
{
intj,key=0;
for(j=0;j{
key=Hash_name(Inf[j].name);//计算哈希地址
while
(1)
{
if(strcmp(H[key].name,NULLKEY)==0)//判断该位置是否为空,不为空就把辅助数组中的元素存到该位置
{
strcpy(H[key].name,Inf[j].name);
strcpy(H[key].phone,Inf[j].phone);
strcpy(H[key].add,Inf[j].add);
break;
}
else
key++;//如果为空,采用线性探测法,将元素后移
}
}
}
//再哈希法
voidagain_put(RecordInf[M],intm,RecordH[M])
{
intj,key=0;
for(j=0;j{
key=Hash_name(Inf[j].name);//计算哈希地址
while
(1)
{
if(strcmp(H[key].name,NULLKEY)==0)//辅助数组中的元素存到该位置
{
strcpy(H[key].name,Inf[j].name);
strcpy(H[key].phone,Inf[j].phone);
strcpy(H[key].add,Inf[j].add);
break;
}
else
key=name_again(Inf[j].name);//再哈希
}}
}
//以号码为关键字的哈希函数
intHash_phone(charphone[20])
{
inti=0;
intb=0;
while(phone[i]!
='\0')//计算电话号码中每个字符的ASCII码值相加
{
b=b+phone[i];
i++;
}
b=b%7;//对小于哈希表的最大素数求余,此处哈希表长为10,对7求余
return(b);
}
//再哈希
intphone_again(charphone[20])
{
inti,h;
h=(int)phone[1];
for(i=2;i<20;i++)
h=h+(int)phone[i];
h=h%7;
returnh;
}
//以电话号码为关键字创建哈希表
voidcreat_phone(RecordInf[M],intm,RecordH[M])
{
intj,key=0;
for(j=0;j{
key=Hash_phone(Inf[j].phone);//计算哈希地址
while
(1)
{
if(strcmp(H[key].phone,NULLKEY)==0)//把辅助数组中的元素存到该位置
{
strcpy(H[key].name,Inf[j].name);
strcpy(H[key].phone,Inf[j].phone);
strcpy(H[key].add,Inf[j].add);
break;
}
else
key++;//如果为空,采用线性探测法,将元素后移
}
}
}
//再哈希法
voidagain_put2(RecordInf[M],intm,RecordH[M])
{
intj,key=0;
for(j=0;j{
key=Hash_phone(Inf[j].phone);//计算哈希地址
while
(1)
{
if(strcmp(H[key].phone,NULLKEY)==0)//判断该位置是否为空,不为空就把辅助数组中的元素存到该位置
{
strcpy(H[key].name,Inf[j].name);
strcpy(H[key].phone,Inf[j].phone);
strcpy(H[key].add,Inf[j].add);
break;
}
else
key=phone_again(Inf[j].phone);//再哈希
}
}
}
//按姓名查找
intSearch_name(RecordH[M],charname[20])
{
inth0;
inti;
inthi;
intresult;
h0=Hash_name(name);
if(H[h0].name==NULLKEY)
{
printf("查找名字不存在!
\n");
return(-1);
}
else
{
result=strcmp(H[h0].name,name);
if(result==0)
return(h0);
else//用线性探测再散列解决冲突
{
for(i=1;i<=M-1;i++)
{
hi=(h0+i)%M;
if(H[hi].name==NULLKEY)
return(-1);
else
{
result=strcmp(H[hi].name,name);
if(result==0)
return(hi);
}
}
return(-1);
}
}
}
//按号码查找
intSearch_phone(RecordH[M],charphone[20])
{
inth0;
inti;
inthi;
intresult;
h0=Hash_phone(phone);
if(H[h0].phone==NULLKEY)
{
printf("查找号码不存在!
\n");
return(-1);
}
else
{
result=strcmp(H[h0].phone,phone);
if(result==0)
return(h0);
else//用线性探测再散列解决冲突
{
for(i=1;i<=M-1;i++)
{
hi=(h0+i)%M;
if(H[hi].phone==NULLKEY)
return(-1);
else
{
result=strcmp(H[hi].phone,phone);
if(result==0)
return(hi);
}
}
return(-1);
}
}
}
//以用户名为关键字的哈希表的输出函数
voidPrint_name(RecordH[M])
{
inti;
printf("\t哈希地址\t用户名\t\t号码\t\t地址\n");
for(i=0;i<10;i++)
{
if(strcmp(H[i].name,"\0")!
=0)
{
printf("\t%d\t\t%s\t\t%s\t\t%s\n",i,H[i].name,H[i].phone,H[i].add);
}
}
}
//以电话号码为关键字的哈希表的输出函数
voidPrint_phone(RecordH[M])
{
inti;
printf("\t哈希地址\t用户名\t\t号码\t\t地址\n");
for(i=0;i<10;i++)
{
if(strcmp(H[i].phone,"\0")!
=0)
{
printf("\t%d\t\t%s\t\t%s\t\t%s\n",i,H[i].name,H[i].phone,H[i].add);
}
}
}
//查找不成功的平均查找长度
voidunsucc_length(intm)
{
charphone[20];
inti,j;
intcount;
intasl=0;
floatunasl;
Hash_phone(phone);
for(i=0;i<7;i++)
{
j=i;
count=1;
while(strcmp(H[j].name,NULLKEY)!
=0)
{
count++;
j=(j+1)%7;
}
asl=asl+count;
}
unasl=(float)asl/7;
printf("查找不成功的平均查找长度为:
%5.2f\n",unasl);
}
voidmain()//主函数
{
charname[20],phone[20];
intm;
intn,p;
intfind;
intw,k;
while
(1)
{
switch(menu())
{
case1:
m=Create(H);//创建辅助数组
break;
case2:
printf("\t\t\t***********************\n");
printf("\t\t\t****1.线性再散列****\n");
printf("\t\t\t****2.再哈希法散列****\n");
printf("\t\t\t****3.退出本菜单****\n");
printf("\t\t\t***********************\n");
printf("输入散列选项<0-2>:
\n");
scanf("%d",&p);
switch(p)
{
case1:
creat_name(Inf,m,H);
Print_name(H);
break;
case2:
again_put(Inf,m,H);
Print_name(H);
break;
}
break;
case3:
printf("\t\t\t***********************\n");
printf("\t\t\t****1.线性再散列****\n");
printf("\t\t\t****2.再哈希法散列****\n");
printf("\t\t\t****3.退出本菜单****\n");
printf("\t\t\t***********************\n");
printf("输入散列选项<0-2>:
\n");
scanf("%d",&n);
switch(n)
{
case1:
creat_phone(Inf,m,H);
Print_phone(H);
break;
case2:
again_put(Inf,m,H);
Print_phone(H);
break;
}
break;
case4:
printf("\t\t\t***********************\n");
printf("\t\t\t****1.按用户名查询****\n");
printf("\t\t\t****2.按电话查询****\n");
printf("\t\t\t****3.退出本菜单****\n");
printf("\t\t\t***********************\n");
printf("输入查找条件<0-2>:
\n");
scanf("%d",&find);
switch(find)
{
case1:
printf("\n请输入要查找的名字:
\n");
scanf("%s",name);
k=Search_name(H,name);
//k=Hash_again(H,name);
if(k!
=-1)
{
printf("查找该人的信息是:
\n");
printf("查找的用户名是:
%s\n",H[k].name);
printf("查找的电话号码是:
%s\n",H[k].phone);
printf("查找的地址是:
%s\n",H[k].add);
}
break;
case2:
printf("请输入要查找的号码:
\n");
scanf("%s",phone);
w=Search_phone(H,phone);
//w=Hash_phone(H,phone);
if(w!
=-1)
{
printf("查找该人的信息是:
\n");
printf("查找的用户名是:
%s\n",H[w].name);
printf("查找的电话号码是:
%s\n",H[w].phone);
printf("查找的地址是:
%s\n",H[w].add);
}
break;
}
break;
case5:
printf("\n");
unsucc_length(m);
printf("\n");
break;
case0:
printf("\n");
printf("欢迎下次使用\n");
printf("\n");
exit(0);
break;
default:
printf("\t\t***********************************\n");
printf("\t\t输入错误,请输入列表中存在的编号\n");
printf("\t\t***********************************\n");
}
printf("\t\t\t*************\n");
printf("\t\t\t按任意键返回\n");
printf("\t\t\t*************\n");
getch();
fflush(stdin);//清空输入缓存
}
}