最小生成树的应用数据结构课程设计.docx
《最小生成树的应用数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《最小生成树的应用数据结构课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
最小生成树的应用数据结构课程设计
课程设计(论文)
题目名称最小生成树的应用
课程名称数据结构课程设计
学生姓名
学号
系、专业信息工程系、通信工程
指导教师
2012年12月23日
摘要
求一个网的最小生成树,即以最低的经济建设n个城市之间的通信网,利用普里姆算法和克鲁斯卡尔算法求这个网的最小生成树。
关键词:
网的最小生成树;Kruskal算法;Prim算法;边和权值。
目录
1问题描述1
2需求分析1
3概要设计1
3.1抽象数据类型定义1
3.2模块划分3
4详细设计5
4.1数据类型的定义5
4.2主要模块的算法描述5
5测试分析13
6课程设计总结13
参考文献16
附录(源程序清单)17
1问题描述
若要在n个城市之间建设通信网络,只需要架设n-1条线路即可。
如何以最低的经济建设这个通信网,是一个网的最小生成树。
2需求分析
(1).可以用连通网来表示n个城市间可能设置的通信网络,其中网的顶点表示城市,边表示两城市之间的路线,边的权值表示相应的费用。
对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。
现在,我们要选择这样一棵生成树,它使总的费用最少,这棵树就是最小生成树。
一棵生成树的费用就是树上各边的费用之和。
(2).本程序的目的是要建设一个最经济的通信网,根据用户输入的网,输出相应的最小生成树。
在这里城市以及两城市之间的费用都用整型数来代替。
利用克鲁斯卡尔算法和普利姆算法实现。
3概要设计
3.1抽象数据类型定义1.ADTGraph
{数据对象V:
v是具有相同特性的数据元素的集合,称为顶点集。
数据关系R:
R={VR}
VR={|v,w属于v且p(v,w),(v,w)表示从v到w的弧,谓词p(v,w)定义了弧的意义或信息}
基本操作:
(1)CreatGraph(&G,V,VR);
初始条件:
V是图的顶点集,VR是图中弧的集合。
操作结果:
按V和VR的定义构造图G。
(2)LocateVex(G,u);
初始条件:
图G存在,u和G中顶点有相同的特征。
操作结果:
若G中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息。
(3)DestoryGraph(&u);
初始条件:
图G存在。
操作结果:
销毁图G。
(4)GetVex(G,v);
初始条件:
图G存在,v是图中某个顶点。
操作结果:
返回v的值。
(5)NextAdjVex(G,v,w);
初始条件:
图G存在,v是图中某个顶点,w是v的邻接顶点。
操作结果:
返回v的(相对于w的)下一个邻接顶点。
若w是v的最后一个邻接点,则返回“空”。
(6)BFSTraverse(G,Visit());
初始条件:
图G存在,Visit是顶点的应用函数。
操作结果:
对图进行广度优先遍历。
在遍历过程中对每个顶点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
}
2.存储结构
Typedefstruct
{
intadj;
intweight;
}AdjMatrix[MAX][MAX];
Typedefstruct
{
djMatrixarc;
intvexnum,arcnum;
}MGraph;
3.2模块划分
本程序包括五个模块:
(1)主函数模块
(2)邻接矩阵定义模块代码
typedefstructArcCell{
intadj;char*info;
}ArcCell,AdjMatrix[20][20];
typedefstruct{
charvexs[20];AdjMatrixarcs;
intvexnum,arcnum;
}MGraph_L;
intlocalvex(MGraph_LG,charv)
{inti=0;while(G.vexs[i]!
=v){++i;}returni;}
(3)创建链接矩阵模块代码
intcreatMGraph_L(MGraph_L&G)
{charv1,v2;inti,j,w;
cout<<"…创建无向图(城市分布图)…"<(46)不包括“()”"<cin>>G.vexnum>>G.arcnum;
for(i=0;i!
=G.vexnum;++i)
{cout<<"输入顶点(城市)"<>G.vexs[i];}
for(i=0;i!
=G.vexnum;++i)
for(j=0;j!
=G.vexnum;++j)
{G.arcs[i][j].adj=int_max;G.arcs[i][j].info=NULL;}
for(intk=0;k!
=G.arcnum;++k)
{cout<<"输入一条边依附的顶点(城市)和权(距离):
(ab3)不包括“()”"<>v1>>v2>>w;
i=localvex(G,v1);j=localvex(G,v2);
G.arcs[i][j].adj=w;G.arcs[j][i].adj=w;}
cout<<"图G邻接矩阵创建成功!
"<(4)最小生成树Prim算法及代价模块代码
(5)最小生成树kruskal算法及代价模块代码
4详细设计
4.1数据类型的定义
(1)树类型
#defineMAXVALUE100
#defineMAXLEAF50
#defineMAXNODEMAXLEAF*2-1;
(2)图类型
typedefstructnode{
intadjvex;
intw;
structnode*nextedge;
}edgenode;
typedefstruct{
chardata;
intid;
edgenode*firstedge;
}vexnode;
4.2主要模块的算法描述
(1)主函数
algraphgra;MGraph_LG;inti,d,g[20][20];
chara='a';d=creatMGraph_L(G);vnodev;
cout<若该图为非强连通图(含有多个连通分量)时"<<<"最小生成树不存在,则显示为非法值"<cout<<"…………………菜单……………………"<cout<<"0、显示该图的邻接矩阵……………………"<cout<<"1、最小生成树PRIM算法及代价…………………"<ints;chary='y';
while(y='y'){cout<<"请选择菜单:
"<>s;
switch(s){
case0:
cout<<"邻接矩阵显示如下:
"<case1:
for(i=0;i!
=G.vexnum;++i)
for(intj=0;j!
=G.vexnum;++j)g[i+1][j+1]=G.arcs[i][j].adj;
cout<<"prim:
"<cout<y/n:
";cin>>y;if(y=='n')break;}
}
图4.1流程图
(2)最小生成树Prim算法及代价模块代码
intprim(intg[][max],intn){
intlowcost[max],prevex[max];inti,j,k,min;intsum=o;
for(i=2;i<=n;i++){lowcost[i]=g[1][i];prevex[i]=1;}
lowcost[1]=0;for(i=2;i<=n;i++)//形成n-1条边的生成树
{min=inf;k=0;
for(j=2;j<=n;j++)
if((lowcost[j]=0)){min=lowcost[j];k=j;}
printf("(%d,%d)%d\t",prevex[k]-1,k-1,min);
sum+=min;lowcost[k]=0;
for(j=2;j<=n;j++)if(g[k][j]{lowcost[j]=g[k][j];prevex[j]=k;}
printf("\n");}
cout<<"最少生成树的代价:
";cout<
否
是
否
是
输入起点st
是
否
结束
图4.2Prim算法流程图
(3)最小生成树kruskal算法及代价模块代码
voidMiniSpanTree(MGraphA*D)//生成最小生成树
{inti,j,n,m,SUM=0;intk=1;
intparent[M];edgeedges[M];
for(i=1;ivexnum;i++)
{for(j=i+1;j<=D->vexnum;j++){if(D->arc[i][j].adj==1)
{edges[k].begin=i;edges[k].end=j;
edges[k].weight=D->arc[i][j].weight;k++;}
}
}
sort(edges,D);
for(i=1;i<=D->arcnum;i++)
{parent[i]=0;}
printf("最小生成树为:
\n");
for(i=1;i<=D->arcnum;i++)//核心部分
{n=Find(parent,edges[i].begin);m=Find(parent,edges[i].end);
if(n!
=m){parent[n]=m;
printf("<<%d,%d>>%d\n",edges[i].begin,edges[i].end,edges[i].weight);
SUM=SUM+edges[i].weight;}
}
图4.3Kruskal算法流程图
5测试分析
测试数据及结果如下:
图5.1创建邻接矩阵
图5.2Prim算法求解
图5.3Kruskal算法求解
6课程设计总结
从这次给我的课程设计任务中我深刻地体会到了编程并非易事。
任何事情并不是想我们想的那样简单和容易。
只有扎扎时时的学习知识才能解决实际生活中的实际问题。
从这次课设中也让我明白以后要多了解相关知识,更多的做一些实践动手活动,将知识运用到实际问题中。
同时,增加自己的动手能力,这样才能便于我们更好的解决问题。
为今后打下好的基础。
实验过程中,我遇到了很多问题,一开始就要建一个图,然后利用kruskal算法解决问题,这个题目是一个十分联系实际的题目,使我更加扎实的掌握了有关数据结构方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。
实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。
过而能改,善莫大焉。
在课程设计过程中,我不断发现错误,不断改正,不断领悟,不断获取。
最终的调试运行环节,本身就是在践行“过而能改,善莫大焉”的知行观。
这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于迎刃而解。
当我完成课程设计后,我感到很欣喜。
能完成让我感到什么叫做编程的快乐,什么叫做乐趣。
也让明白要想把通信工程这门专业学好必须持之以恒地努力下去。
参考文献
[1]黄同成,黄俊民,董建寅.数据结构[M].北京:
中国电力出版社,2008
[2]董建寅,黄俊民,黄同成.数据结构实验指导与题解[M].北京:
中国电力出版社,2008
[3]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:
清华大学出版社,2002
[4]刘振鹏,张晓莉,郝杰.数据结构[M].北京:
中国铁道出版社,2003
附录(源程序清单)
#include
#include
usingnamespacestd;
#defineint_max10000
#defineinf9999
#definemax20
#defineMAX20
#defineM20
typedefstructArcCell
{intadj;char*info;
}ArcCell,AdjMatrix[20][20];
typedefstruct
{charvexs[20];AdjMatrixarcs;intvexnum,arcnum;
}MGraph;
intlocalvex(MGraphG,charv)
{inti=0;while(G.vexs[i]!
=v){++i;}returni;}
voidljjzprint(MGraphG)
{inti,j,n=0;printf("建立的邻接矩阵如下:
\n");printf("\n");
printf("_____________________________________________\n");
for(i=0;i!
=G.vexnum;i++)
{for(j=0;j!
=G.vexnum;j++)
{if(j==0)printf("");
printf("%d",G.arcs[i][j].adj);printf("");n++;
if(n==G.vexnum){printf("\n");n=0;}}
}
printf("______________________________________________\n");}
intcreatMGraph(MGraph&G)
{charv1,v2;inti,j,w;
printf("建立邻接矩阵:
\n");
printf("请输入图G顶点(城市)和弧(边)的个数:
");
scanf("%d",&G.vexnum);scanf("%d",&G.arcnum);printf("输入所有顶点:
");
for(i=0;i>G.vexs[i];}
for(i=0;ifor(j=0;jprintf("输入所有边及依附的顶点(城市)和权(距离):
\n");
for(intk=0;k{cin>>v1>>v2>>w;i=localvex(G,v1);j=localvex(G,v2);
G.arcs[i][j].adj=w;G.arcs[j][i].adj=w;}
ljjzprint(G);
printf("图G邻接矩阵创建成功!
\n");
returnG.vexnum;}intvisited[max];intwe;
typedefstructarcnode
{intadjvex;structarcnode*nextarc;char*info;}arcnode;
typedefstructvnode
{chardata;arcnode*firstarc;}vnode,adjlist;
typedefstruct//图的定义
{adjlistvertices[max];intvexnum,arcnum;intkind;}algraph;
intprim(intg[][max],intn)//最小生成树PRIM算法
{intlowcost[max],prevex[max];inti,j,k,min;intsum=0;
for(i=2;i<=n;i++){lowcost[i]=g[1][i];prevex[i]=1;}
lowcost[1]=0;
for(i=2;i<=n;i++){min=inf;k=0;
for(j=2;j<=n;j++)
if((lowcost[j]=0)){min=lowcost[j];k=j;}
printf("(%d,%d)%d\t",prevex[k]-1,k-1,min);sum+=min;lowcost[k]=0;
for(j=2;j<=n;j++)if(g[k][j]printf("\n");}
cout<<"最少生成树的代价:
";cout<typedefstruct{intbegin;intend;intweight;}edge;
typedefstruct{intadj;intweight;}Adj[MAX][MAX];
typedefstruct{Adjarc;intvexnum,arcnum;}MGraphA;
voidCreatGraph(MGraphA*);//函数申明
voidsort(edge*,MGraphA*);
voidMiniSpanTree(MGraphA*);
intFind(int*,int);
voidSwapn(edge*,int,int);
voidCreatGraph(MGraphA*D)//构件图
{inti,j,n,m;
printf("请输入边数和顶点数:
");
scanf("%d%d",&D->arcnum,&D->vexnum);
for(i=1;i<=D->vexnum;i++)//初始化图
{for(j=1;j<=D->vexnum;j++){D->arc[i][j].adj=D->arc[j][i].adj=0;}}
for(i=1;i<=D->arcnum;i++)//输入边和权值
{printf("\n请输入有边的2个顶点");scanf("%d%d",&n,&m);
while(n<0||n>D->vexnum||m<0||n>D->vexnum)
{printf("输入的数字不符合要求请重新输入:
");scanf("%d%d",&n,&m);}
D->arc[n][m].adj=D->arc[m][n].adj=1;getchar();
printf("\n请输入%d与%d之间的权值:
",n,m);scanf("%d",&D->arc[n][m].weight);}
printf("邻接矩阵为:
\n");
for(i=1;i<=D->vexnum;i++)
{for(j=1;j<=D->vexnum;j++)
{printf("%d",D->arc[i][j].adj);}printf("\n");}
}
voidsort(edgeedges[],MGraphA*D)//对权值进行排序
{inti,j;
for(i=1;iarcnum;i++)
{for(j=i+1;j<=D->arcnum;j++)
{if(edges[i].weight>edges[j].weight){Swapn(edges,i,j);}}
}
printf("权排序之后的为:
\n");
for(i=1;iarcnum;i++)
{printf("<<%d,%d>>%d\n",edges[i].begin,edges[i].end,edges[i].weight);}
}
voidSwapn(edge*edges,inti,intj)//交换权值以及头和尾
{inttemp;temp=edges[i].begin;edges[i].begin=edges[j].begin;
edges[j].begin=temp;temp=edges[i].end;
edges[i].end=edges[j].end;edges[j].end=temp;
temp=edges[i].weight;edges[i].weight=edges[j].weight;
edges[j].weight=temp;}
voidMiniSpanTree(MGraphA*D)//生成最小生成树
{inti,j,n,m,SUM=0;intk=1;
intparent[M];edgeedges[M];
for(i=1;ivexnum;i++)
{for(j=i+1;j<=D->vexnum;j++)
{if(D->arc[i][j].adj==1){edges[k].begin=i;edges[k].end=j;edges[k].weight=D->arc[i][j].weight;k++;}}
}
sort(edges,D);
for(i=1;i<=D->arcnum;i++)
{parent[i]=0;}printf("最小生成树为:
\n");
for(i=1;i<=D->arcnum;i++)//核心部分
{n=Find(parent,edges[i].begin);m=Find(parent,edges[i].end);
if(n!
=m){parent[n]=m;printf("<<%d,%d>>%d\n",
edges[i].begin,edges[i].end,edges[i].weight);SUM=SUM+edges[i].weight;}
}cout<<"最少生成树的代价:
";cout<intFind(int*parent,intf)//找尾
{while