最小生成树数据结构课程设计报告.docx
《最小生成树数据结构课程设计报告.docx》由会员分享,可在线阅读,更多相关《最小生成树数据结构课程设计报告.docx(16页珍藏版)》请在冰豆网上搜索。
![最小生成树数据结构课程设计报告.docx](https://file1.bdocx.com/fileroot1/2023-1/22/1c59c075-2023-42d7-8ccf-27ae731a5bf1/1c59c075-2023-42d7-8ccf-27ae731a5bf11.gif)
最小生成树数据结构课程设计报告
河北科技大学
课程设计报告
学生姓名:
白云学号:
Z110702301
专业班级:
计算机113班
课程名称:
数据结构课程设计
学年学期:
2013—2014学年第2学期
指导教师:
郑广
2014年6月
课程设计成绩评定表
学生姓名
白云
学号
Z110702301
成绩
专业班级
计算机113
起止时间
2014.6.23—2014.6.27
设计题目
指
导
教
师
评
语
学习态度出勤情况:
好□较好□一般□较差□
课题工作量:
饱满□较大□合理□较小□
综合运用知识能力:
好□较好□一般□较差□
方案设计情况:
合理□较合理□基本合理□不合理□
课题结果分析能力:
强□较强□一般□较差□
设计实现情况:
全部□大部分□部分□未实现□
设计报告内容:
详细□完整□较完整□不完整□
设计报告文档格式:
规范□较规范□基本规范□不规范□
独立动手能力:
强□较强□一般□较差□
指导教师:
年月日
一、需求分析说明
1.1最小生成树总体功能要求
在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。
存储结构采用多种。
求解算法多种。
1.2基本功能
在n个城市之间建设网络,只需要架设n-1条线路,建立最小生成树即可实现最经济的架设方法。
程序可利用克鲁斯卡尔算法或prim算法生成最小生成树。
1.3模块分析
主模块:
用于生成界面和调用各个子模块。
Kruscal模块:
以kruscal算法实现最小生成树。
Prim模块:
以prim算法实现最小生成树。
邻接表模块:
用邻接表方式存储图。
邻接表输出模块:
输出邻接表。
邻接矩阵模块:
用邻接矩阵方式存储图。
邻接矩阵模块:
输出邻接矩阵。
二、概要设计说明
2.1设计思路
问题的解决分别采用普利姆算法以及克鲁斯卡尔算法。
1)普利姆算法就是先选择根,把它放入一个集合U中,剩余的顶点放在集合V中。
然后选择该顶点与V中顶点之间权值最小的一条边,以此类推,如果达到最后一个则返回上一个顶点。
2)克鲁斯卡尔算法就是写出所有的顶点,选择权最小的边,然后写出第二小的,以此类推,最终要有一个判断是否生成环,不生成则得到克鲁斯卡尔的最小生成树。
2.2模块调用图
Kruscal模块
Prim模块
邻接矩阵输出模块
邻接表输出模块
2.3数据结构设计
2.3.1.抽象数据类型
ADTGraph
{
数据对象V:
v是具有相同特征的数据元素的集合,成为顶点集。
数据关系R:
R={VR}
VR={|v,w属于v且p(v,w)表示从v到w的弧,谓词p(v,w)定义了弧的意义或信息}
基本操作:
1)GreatGraph(&G,V,VR)
初始条件:
V是图的顶点集,VR是图中弧的集合。
操作条件:
按V和VR的定义构造图G。
2)LocateVex(G,u)
初始条件:
图G存在,u和G中顶点有相同的特征。
操作条件:
若G中存在顶点u,则返回该顶点在图中的位置,否则返回其他信息。
2.3.2方法描述
#defineint_max10000/*节点不可达的距离*/
#definemax20/*数组最大长度*/
intcreatMGraph_L(MGraph_L&G)//用邻接矩阵存储
voidljjzprint(MGraph_LG)//输出邻接矩阵
intcreatadj(algraph&gra,MGraph_LG)//用邻接表存储图
voidadjprint(algraphgra)//输出邻接表
intprim(intg[][max],intn)//prim算法
voidkruscal_arc(MGraph_LG,algraphgra)//最小生成树kruscal算法
三、详细设计说明
3.1主函数模块
首先调用creatMGraph_L()函数进行邻接矩阵的初始化,然后调用creatadj()函数进行邻接表的初始化,然后根据用户输入判断switch()调用哪个模块。
3.2邻接表输出子模块
首先判断是否超出了数据的个数,如果没有则输出邻接表的头节点,如果头节点的指针域不为空则输出下一个表结点,以此类推。
3.3邻接矩阵输出子模块
判断是否超出了数据的个数,如果没有则输出G.arcs[i][j].adj中的值。
3.4创建邻接矩阵子模块
输入顶点和弧的个数,再输入顶点与顶点之间的权值,生成邻接矩阵
3.5创建邻接表子模块
根据表结构定义一个表,设置表头结点为空,再循环生成其它结点并连接到上一个结点的后面。
3.6Prim子模块
标志顶点1加入U集合,形成n-1条边的生成树,寻找满足边的一个顶点在U,另一个顶点在V中的最小边,顶点K加入U,修改由顶点K到其他顶点边的权值,最后得到最小生成树。
3.7Kruscal子模块
确定弧的结点,以及弧的权,比较弧的权的大小并对权小的赋值,确定结点的位置,确保不能生成换,最后的到最小生成树。
四、调试分析
4.1实际完成情况说明
程序完成了prim和kruscal求一个图的最小生成树,并对图以邻接表和邻接矩阵的形式进行存储。
4.2出现的问题及解决方案
1)数据之间类型不同,引发数据间交换紊乱。
指针空间未分配导致系统随机给出一个错误的数据
2)在寻找下一个结点时,寻找到最小权值边,将其两端的顶点信息及变的权值存储道辅助数组中。
在设计解决这些问题时用多个for循环嵌套查找,判断。
3)一些小细节尤其要注意,比如变量的定义,定义的位置。
4.3程序中可以改进的地方
程序中对于一些没有最小生成树的图,没有判断功能。
还有就是进行完一个图的运算要关闭程序再重新输入新的图。
五、用户使用说明
输入正确的数据
程序执行菜单
邻接矩阵存储
邻接表存储
Prim算法
Kruscal算法
六、课程设计总结
通过这次课程设计,我收获了不少的东西。
我选择的题目是最小生成树,这个问题看这简单,但是做起来有非常大的困难。
平时我们很注重理论学习,但现在看来,实践也是非常重要的,两者缺一不可。
在这期间我遇到了不少的问题,问同学,查资料,虽然过程是辛苦琐碎的,但最后成果出来还是很鼓舞人心的。
七、测试数据
1:
城市的个数和线路个数:
5,6
2:
各个城市的名称:
a,b,c,d,e
3:
每条路径的权值:
ad1,ab1,bc1,bd1,de1,ce2
八、参考书目
[1]汤文兵.数据结构.北京:
清华大学出版社,2011
[2]李春葆.数据结构——习题与解析.北京:
清华大学出版社,2010
[3]MarkAllenWeiss.DataStructuresandAlgorithmAnalysisinC:
SecondEdition.NewYork:
MITPress,2007
[4]郭翠英.C语言课程设计案例精编.北京:
中国水利出版社,2011
源代码
#include
#include
#include
//usingnamespacestd;
#defineint_max10000
#defineinf9999
#definemax20
typedefstructArcCell{
intadj;
char*info;
}ArcCell,AdjMatrix[20][20];
typedefstruct{
charvexs[20];//定义一个顶点数组
AdjMatrixarcs;//定义一个邻接矩阵
intvexnum;
intarcnum;
}MGraph_L;
intlocalvex(MGraph_LG,charv){
inti=0;
while(G.vexs[i]!
=v){
++i;
}
returni;
}
intcreatMGraph_L(MGraph_L&G){
charv1,v2;
inti,j,w;
cout<<"请输入城市个数和总道路的个数:
"<cin>>G.vexnum>>G.arcnum;
for(i=0;i!
=G.vexnum;++i){
cout<<"输入城市名"<
cin>>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<<"请输入两城市之间的距离:
"<cin>>v1>>v2>>w;//输入一条边依附的两点及权值
i=localvex(G,v1);
j=localvex(G,v2);
G.arcs[i][j].adj=w;
//G.arcs[j][i].adj=w;
}
cout<<"***********************************************"<cout<<"图创建成功"<cout<<"请根据如下进行操作"<returnG.vexnum;
}
voidljjzprint(MGraph_LG){//输出邻接矩阵
inti,j;
for(i=0;i!
=G.vexnum;++i){
for(j=0;j!
=G.vexnum;++j)
if(G.arcs[i][j].adj==10000)
{cout<<"0"<<"";}
else
{
cout<}cout<}
}
typedefstructarcnode{//定义表结点
intadjvex;//该弧指向的顶点在图中的位置
structarcnode*nextarc;//链域,指向下一条边或弧的结点
char*info;//该弧的信息
}arcnode;
typedefstructvnode{//临街链表顶点头结点
chardata;//数据
arcnode*firstarc;//链域
}vnode,adjlist;
typedefstruct{//表的定义
adjlistvertices[max];//定义头结点
intvexnum,arcnum;//图的当前顶点数和弧数
intkind;//图的种类标志
}algraph;
typedefstructacr{//弧的定义
intpre;//弧的一结点
intbak;//弧的另一结点
intweight;//弧的权
}edg;
intcreatadj(algraph&gra,MGraph_LG){//用邻接表存储图
inti=0,j=0;
arcnode*arc,*tem,*p;
for(i=0;i!
=G.vexnum;++i){//邻接表的初始化
gra.vertices[i].data=G.vexs[i];//将abcde放入顶点信息域
gra.vertices[i].firstarc=NULL;//指针域为空
}
for(i=0;ifor(j=0;jif(gra.vertices[i].firstarc==NULL){
if(G.arcs[i][j].adj!
=int_max&&jarc=(arcnode*)malloc(sizeof(arcnode));
arc->adjvex=j;
gra.vertices[i].firstarc=arc;
arc->nextarc=NULL;
p=arc;
}
}else{
if(G.arcs[i][j].adj!
=int_max&&j!
=G.vexnum){
tem=(arcnode*)malloc(sizeof(arcnode));
tem->adjvex=j;
p->nextarc=tem;
tem->nextarc=NULL;
p=tem;
}
}
}
}
gra.vexnum=G.vexnum;
gra.arcnum=G.arcnum;
return1;
}
voidadjprint(algraphgra){//输出邻接表
inti;
for(i=0;i!
=gra.vexnum;++i){
arcnode*p;
cout<";
p=gra.vertices[i].firstarc;
while(p!
=NULL){
cout<<"->"<adjvex;
p=p->nextarc;
}
cout<}
}
typedefstruct{
intadjvex;
intlowcost;
}closedge;
intprim(intg[][max],intn){//prim算法
intlowcost[max],prevex[max];//lowcost[]存储当前集合U分别到剩余结点的最短路径prevex[]存储最短路径在U中的结点
inti,j,k,min;
for(i=2;i<=n;i++){
lowcost[i]=g[1][i];//初始化
prevex[i]=1;//顶点未加入到最小生成树中
}
lowcost[1]=0;//标志顶点1加入U集合
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);
lowcost[k]=0;//顶点K加入U
for(j=2;j<=n;j++)
if(g[k][j]lowcost[j]=g[k][j];
prevex[j]=k;
}
printf("\n");
}
return0;
}
intarcvisited[100];//kruscal弧标记数组
intfind(intarcvisited[],intf){
while(arcvisited[f]>0)
f=arcvisited[f];
returnf;
}
voidkruscal_arc(MGraph_LG,algraphgra){//最小生成树kruscal算法
edgedgs[20];
inti,j,k=0;
for(i=0;i!
=G.vexnum;++i)
for(j=i;j!
=G.vexnum;++j){
if(G.arcs[i][j].adj!
=10000){
edgs[k].pre=i;
edgs[k].bak=j;
edgs[k].weight=G.arcs[i][j].adj;
++k;
}
}
intx,y,m,n;
intbuf,edf;
for(i=0;i!
=gra.arcnum;++i)
arcvisited[i]=0;
for(j=0;j!
=G.arcnum;++j){
m=10000;
for(i=0;i!
=G.arcnum;++i){
if(edgs[i].weightm=edgs[i].weight;
x=edgs[i].pre;
y=edgs[i].bak;
n=i;
}
}
buf=find(arcvisited,x);
edf=find(arcvisited,y);
edgs[n].weight=10000;
if(buf!
=edf){
arcvisited[buf]=edf;
cout<<"("<cout<}
}
}
voidmain(){
algraphgra;
MGraph_LG;
inti,j,d,g[20][20];
chara='a';
d=creatMGraph_L(G);
creatadj(gra,G);
cout<<"*****************************************"<cout<<"**1.用邻接矩阵存储:
*********************"<cout<<"**2.用邻接表存储:
*********************"<cout<<"**3.PRIM算法实现:
*********************"<cout<<"**4.KRUSCAL算法实现:
*********************"<ints;
chary='y';
while(y='y'){
cout<<"请选择菜单:
"<cin>>s;
switch(s){
case1:
cout<<"用邻接矩阵存储为:
"<ljjzprint(G);
break;
case2:
cout<<"用邻接表存储为:
"<adjprint(gra);
break;
case3:
for(i=0;i!
=G.vexnum;++i)
for(j=0;j!
=G.vexnum;++j)
g[i+1][j+1]=G.arcs[i][j].adj;
cout<<"PRIM算法最经济的架设方法为:
"<prim(g,d);
break;
case4:
cout<<"KRUSCAL算法最经济的架设方法为:
"<kruscal_arc(G,gra);
break;
}
cout<y/n:
";
cin>>y;
if(y=='n')
break;
}
}
THANKS!
!
!
致力为企业和个人提供合同协议,策划案计划书,学习课件等等
打造全网一站式需求
欢迎您的下载,资料仅供参考