数据结构课程设计哈希表最小代价生成树.docx
《数据结构课程设计哈希表最小代价生成树.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计哈希表最小代价生成树.docx(20页珍藏版)》请在冰豆网上搜索。
数据结构课程设计哈希表最小代价生成树
数据结构课程设计报告
学院:
班级:
姓名:
学号:
设计题目:
(1)哈希表查找的设计
(2)连通网的最小代价生成树
设计时间:
2014年1月2日至1月7日
(一)
课题三哈希表查找的设计
一、问题分析和任务定义
设哈希表长为20,用除留余数法构造一个哈希函数,以开放定址法中的线性探测再散列法作为解决冲突的方法,编程实现哈希表查找、插入和建立算法。
二、软件设计
(1)程序框图
开始→构造哈希表→输入数据元素→求得哈希地址→装入哈希表→查找元素→插入元素→结束
(2)子函数
1)初始化哈希表
动态分配存储空间
2)求得哈希地址
除留余数法
3)冲突处理
线性探测再散列法
4)输入元素
输入元素个数→循环体输入元素→考虑冲突处理→依次存入哈希地址
5)打印哈希表
6)查找元素
直接去哈希地址比较查找→考虑冲突处理
7)插入元素
查找元素→考虑冲突次数是否过多→插入哈希表
(3)结构体
1)哈希表结构体
装有数据元素的地址;现有数据个数;哈希表长
三、编码实现
源代码如下:
#include
#include
#defineStatusint
#defineElemTypeint
#defineKeyTypeint
#defineNULLKEY0
#defineEQ(x,y)x==y
#defineSUCCESS1
#defineUNSUCCESS0
#defineDUPLICATE-1
#defineOK1
#defineMAXHSIZE20
#defineOVERFLOW-2
#defineNULL0
inthashsize[]={20};
typedefstruct
{
ElemType*elem;
intcount;
intsizeindex;
}HashTable;
StatusInitHashTable(HashTable*H)
{
H->elem=(int*)malloc(hashsize[0]*sizeof(ElemType));
if(!
H->elem)exit(OVERFLOW);
H->count=0;
H->sizeindex=hashsize[0];
for(inti=0;iH->elem[i]=0;
returnOK;
}
StatusHash(ElemTypee)//求得哈希地址
{
ElemTypei;
i=e%MAXHSIZE;
returni-1;
}
Statuscollision(ElemType*p,constElemType*c)
{
//(*p)+=*c;
*p=(*p)+(*c);
if(*p>MAXHSIZE)
exit(OVERFLOW);
elsereturnSUCCESS;
}
StatusInputData(HashTable*H,int*p,int*c)
{
inti,n,t1,t2,t3;
int*pa;
printf("请输入元素个数:
");
//n=getchar();
scanf("%d",&n);
pa=(int*)malloc(n*sizeof(int));
printf("开始输入数据:
\n");
for(i=0;i{
//scanf("%d",&t);
scanf("%d",(pa+i));
//printf("%d",*(pa+i));
*p=Hash(*(pa+i));
//printf("%d",*(pa+i));
//t1=(H->elem[*p]!
=NULLKEY);
//t2=!
(EQ(*(pa+i),H->elem[*p]));
//printf("%d",*(pa+i));
while((H->elem[*p]!
=NULLKEY)&&!
(EQ(*(pa+i),H->elem[*p])))
{
t3=++(*c);
collision(p,c);
}
H->elem[*p]=*(pa+i);
H->count++;
}
return0;
}
StatusPrintHash(HashTable*H)
{
inti;
printf("当前哈希表如下:
\n");
for(i=0;i>1;++i)
{
printf("%5d",H->elem[i]);
}
putchar('\n');
for(;i{
printf("%5d",H->elem[i]);
}
putchar('\n');
printf("按任意键继续\n");
getchar();
getchar();
//Menu();
return0;
}
StatusSearchHash(HashTableH,KeyTypeK,int*p,int*c)
{
intt;
*p=Hash(K);
while(H.elem[*p]!
=NULLKEY&&!
(EQ(K,H.elem[*p])))
{
t=++(*c);
collision(p,&t);
}
if(EQ(K,H.elem[*p]))
returnSUCCESS;
elsereturnUNSUCCESS;
}
StatusInsertHash(HashTable*H,ElemTypee)
{
intc=0;
intp;
p=Hash(e);
//printf("%d",e);
if(SearchHash(*H,e,&p,&c))
returnDUPLICATE;
elseif(csizeindex/2)
{
H->elem[p]=e;
++H->count;
returnOK;
}
else
{
returnUNSUCCESS;
}
}
StatusRecreateHashTable(HashTable*H)
{
printf("你需要重新构造哈希表\n");
return0;
}
voidmain()
{
HashTableHH;
intpp=0,cc=0;
intt=0,key=0,*p=&pp,*c=&cc;
HashTable*H=&HH;
InitHashTable(H);//初始化哈希表,分配内存
InputData(H,p,c);//构造哈希表,输入元素数据
PrintHash(H);//打印哈希表
printf("请输入查找元素:
");//开始查找
scanf("%d",&key);
t=SearchHash(*H,key,p,c);
if(t)
{
printf("查找成功!
\n");
PrintHash(H);
}
elseprintf("哈希表中无此元素\n");
printf("请输入要插入的元素:
");//开始插入
scanf("%d",&key);
t=InsertHash(H,key);
if(t)
{
printf("插入成功!
\n");
PrintHash(H);
}
elseRecreateHashTable(H);
}
四、软件测试
(1)编译环境为MicrosoftVisualStudio2010,运行哈希表.exe,
(2)输入元素个数10
(3)输入数据3,5,8,43,54,21,8,10,9,17,得到哈希表
(4)输入查找元素5,提示查找成功,说明此哈希表含有元素5
(5)若输入查找元素23,则提示哈希表中无此元素
(5)插入元素23,提示插入成功,并显示当前哈希表
(6)结论:
程序顺利完成了使用除留余数法构建哈希表,使用线性探测再散列处理冲突,查找元素和插入元素的功能,达到了预期目的。
(二)
课题四连通网的最小代价生成树
一、问题分析和任务定义
如下图要在n个城市之间建立通讯联络网,则连通n个城市只需要修建n-1条线路,编程实现在最节省经费的前提下建立这个通讯网。
图2
图1
将图1等效为图2进行分析。
如图2,这是一个含有6个顶点10条边的连通网,圆圈内的数字为顶点信息,边上的数字为权值。
由题意,要求图1的通讯联络网最节省经费方案即转化求为图2的最小生成树问题。
于是本次任务即为编程实现最小生成树的构造。
五、软件设计
(1)程序框架
(2)子函数
1)确定某个元素在图中的位置
循环体,判断
2)构造连通网
定义结构体变量→循环体输入顶点元素→初始化邻接矩阵→循环体输入边及权值
3)打印连通网(邻接矩阵的存储结构)
内嵌的循环体
4)构造最小生成树
初始化辅助数组→将起始元素u加入数集U→选择其余的n-1个点→打擂台法确定最小值→选择数集V-U中最小的权值→打印所求的边(最小生成树的树枝)→将新结点归入数集U→更新数集V-U中的最小权值及其对应顶点
(3)结构体
1)顶点信息结构体(存储权值信息或是连接于非连接信息)
2)图的数组存储结构体
3)最小生成树的辅助数组结构体
六、编码实现
源代码如下:
#defineINFINITY999
#defineMAX_VERTEX_NUM20
#defineVertexTypeint
#defineVRTypeint
#defineNULL0
#defineInfoTypeint
typedefintGraphKind[10];
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
typedefintStatus;
typedefintBoolean;
typedefstructArcCell
{
VRTypeadj;//顶点类型,可以是权值信息或是连接于非连接信息
InfoType*info;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{
VertexTypevexs[MAX_VERTEX_NUM];
AdjMatrixarcs;
intvexnum;
intarcnum;
GraphKindkind;
}MGraph;
struct
{
VertexTypeadjvex;
VRTypelowcost;
}closedge[MAX_VERTEX_NUM];
intLocateVex(MGraphG,VertexTypeu)
{/*初始条件:
图G存在,u和G中顶点有相同特征
操作结果:
若G中存在顶点u,则返回该顶点在图中位置;否则返回-1*/
inti;
for(i=0;i{
if(u==G.vexs[i])
returni;
}
return-1;
}
intCreateUDN(MGraph*G)
{
inti,j,k;
intv1,v2,w;
intt1,t2,t3;
//intIncInfo;
printf("请输入元素个数和边数:
");
scanf("%d%d",&t1,&t2);
G->vexnum=t1;
G->arcnum=t2;
printf("开始输入元素:
\n");//对结构体变量输入元素
for(i=0;ivexnum;++i)
{
scanf("%d",&t3);
G->vexs[i]=t3;
}
for(i=0;ivexnum;++i)//初始化邻接矩阵
for(j=0;jvexnum;++j)
{
G->arcs[i][j].adj=INFINITY;
G->arcs[i][j].info=0;
}
printf("开始输入边及权值,格式为边n:
顶点1顶点2权值\n");
for(k=0;karcnum;++k)//输入边及权值
{
printf("边%d:
",k+1);
scanf("%d%d%d",&v1,&v2,&w);
i=LocateVex(*G,v1);j=LocateVex(*G,v2);
G->arcs[i][j].adj=w;
if(G->arcs[i][j].info)
scanf("%d",G->arcs[i][j].info);
G->arcs[j][i]=G->arcs[i][j];
}
returnOK;
}
voidPrintMGraph(MGraph*G)
{
inti,j;
printf("图的邻接矩阵表示为:
\n");
for(i=0;ivexnum;++i)
{
for(j=0;jvexnum;++j)
printf("%-5d",G->arcs[i][j].adj);
printf("\n");
}
}
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu)
{
inti,j,k,m=0,n=0,t=0;
k=LocateVex(G,u);//确定起始元素u在矩阵图中的位置
for(j=0;jif(j!
=k)
{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j].adj;
}
closedge[k].lowcost=0;//将起始元素u加入数集U
for(i=1;i{
m=0;
//k=minimum(closedge);
while(!
closedge[m].lowcost)
m++;
t=closedge[m].lowcost;//打擂台法确定最小值,但是要保证t的初值不为零
for(m=0;m{
if((closedge[m].lowcost!
=0)&&(closedge[m].lowcost<=t))
{
t=closedge[m].lowcost;
n=m;
//k=m;
}
}
k=n;
printf("(%d,%d)",closedge[k].adjvex,G.vexs[k]);//打印所求的边(最小生成树的树枝)
closedge[k].lowcost=0;//将新结点归入数集U
for(j=0;j{
if(G.arcs[k][j].adj{
closedge[j].adjvex=G.vexs[k];//顶点信息
closedge[j].lowcost=G.arcs[k][j].adj;//权值信息
}
}
}
}
voidmain()
{
intu;
MGraphGG;
MGraph*G=&GG;
CreateUDN(G);
PrintMGraph(G);
printf("要开始生成图的最小生成树,请输入顶点信息:
");
scanf("%d",&u);
printf("最小生成树为:
\n");
MiniSpanTree_PRIM(*G,u);
printf("\n");
getchar();
getchar();
}
七、软件测试
(1)编译环境为MicrosoftVisualStudio2010,运行最小生成树.exe,
(2)输入元素个数6,边数10
(3)输入元素:
123456
(4)输入各边及权值数据,出现图的邻接矩阵表示,其中999代表顶点不相邻
(5)输入顶点,开始生成最小生成树
(6)最小生成树为(1,6)(6,2)(1,5)(6,3)(1,4)
结论:
程序顺利完成了构造最小生成树的功能,
得到了最后解决方案如右图所示:
(三)
心得体会:
这四天的数据结构课程设计,我顺利完成了两个课题。
应该说过程是辛苦的,但收获是丰盛的。
我耐心写好课题规划,设计程序框图,我不担心准备的时间过长,因为我觉得准备充分了后面才做得顺利,才不需要返工。
事实正是如此,我分析了任务定义,详细研究了哈希表和最小代价生成树的思路和算法,然后画出大致的程序框图,理清思路,边写代码边参考我拟定的程序框图,这样代码写下来就更加清晰。
但是书本给的算法并不是完整的代码语言,我在将算法思想转化为代码语言时也遇到过诸如指针引用不当,类型不匹配等令人恼怒的问题。
在不断调试的过程中,我还自己摸索了VC2010编译器强大的调试功能,像设置断点,查看局部变量等功能。
借助编译器,我一步一步调试,缩小错误范围,找到并修正错误,最后完成了程序调试,出结果的那一瞬间,我激动万分。
的确,自己亲手做课程设计是挺辛苦,但我知道,过程越是坎坷曲折,收获的知识与能力越是刻骨铭心。