构造可以使N个城市连接的最小生成树Word格式文档下载.docx
- 文档编号:19467203
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:17
- 大小:125.38KB
构造可以使N个城市连接的最小生成树Word格式文档下载.docx
《构造可以使N个城市连接的最小生成树Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《构造可以使N个城市连接的最小生成树Word格式文档下载.docx(17页珍藏版)》请在冰豆网上搜索。
通过邻接矩阵的建立,可以将任意两点的权值存入其中,便于进行各边的权值的比较修改,在普利姆算法中,为实现这个算法需附设一个辅助数组closedge,以记录从U到V-U具有最小代价的边,对每个顶点vi∈V-U,在辅助数组中存在一个相应分量closedge[i-1],他包括两个域,其中lowcost存储该边上的权值。
显然,
closedge[i-1].lowcost=Min{cost(u,vi)|u∈U}
从算法可以看出每加入一个顶点到U中,closedge数组都会发生相应的变化。
程序模块之间的调用:
在主函数中调用邻接矩阵的初始化函数,邻接矩阵的生成函数,PRIM算法的函数,图的构造函数,输出函数。
邻接矩阵的生成函数主要解决的是边的信息存储问题,而PRIM算法的函数是解决计算出最小生成树的功能。
(5)抽象数据类型结构体数组的定义:
#ifndefADJACENCYMATRIXED//防止该头文件被重复引用
#defineADJACENCYMATRIXED//而引起的数据重复定义
#defineINFINITY32767//最大值∞
#defineMAX_VERTEX_NUM20//最大顶点个数
typedefintVRType;
//权值,即边的值
typedefcharInfoType;
//附加信息的类型,后面使用时会定义成一个指针
typedefcharVertexType[MAX_VERTEX_NUM];
//顶点类型
typedefenum{DG=1,DN,UDG,UDN}GraphKind;
//{有向图,有向网,无向图,无向网}
typedefstructArcCell
{
VRTypeadj;
//VRType是顶点关系类型。
对无权图,用1或0表示相邻否;
对带权图,则为权值类型。
InfoType*info;
//该弧关系信息的指针
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
VertexTypevexs[MAX_VERTEX_NUM];
//顶点向量
AdjMatrixarcs;
//邻接矩阵
intvexnum,arcnum;
//图的当前顶点数和弧数
GraphKindkind;
//图的种类标志
}MGraph;
typedefstruct//普里姆算法辅助数组的定义
{
VertexTypeadjvex;
VRTypelowcost;
}closedge[MAX_VERTEX_NUM];
#endif//结束if
(6)程序模块
MGraphG;
//网G,唯一的全局变量
intmain(intargc,char*argv[]);
//主函数
StatusLocateVex(MGraphG,VertexTypev);
//判断城市v在网G中的位置
StatusCreateUDN(MGraph&
G);
//创建网G的邻接矩阵
voidDisplayNet(MGraphG);
//以邻接矩阵的形式显示网G
voidMiniSpanTree_KRUSKAL(MGraphG);
//最小生成树的Kruskal算法
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu);
//最小生成树的Prim算法
StatusMinimum(closedgecloseEdge,intn);
//Prim算法中求下一个城市的函数
voidDeleteInfo(MGraph&
//释放堆内存上动态申请的空间
(7)流程图
创建用邻接矩阵表示的城市道路网
输入城市数G.vexnum、
道路数G.arcnum
输入城市名G.vexs[i]
输入表示道路的两个城市及
道路值G.arcs[i][j].adj
返回OK
2.3.1创建邻接矩阵的流程图(N-S图)
Prim算法
化辅助数组closeEdge
for(i=1;
i<
G.vexnum;
++i)
求下一个城市k=Minimum(closeEdge,G.vexnum)
输出找到的道路
标记城市,避免重复
输出总耗费
图2.3.2Prim算法流程图(N-S图)
三、详细设计
(1)图的建立:
MGraphCreateMarph(MGraph&
G){
intv1,v2,weight,i,j,k;
printf("
●●请输入无向图的顶点数和边数:
"
);
scanf("
%d%d"
&
G.vexnum,&
G.arcnum);
for(i=0;
i<
i++){//初始化邻接矩阵
for(j=0;
j<
j++){
G.arcs[i][j]=0;
}}
i++){
printf("
第%d个顶点的序号:
i+1);
scanf("
%d"
G.vexs[i]);
}
\n---------------请你确定各条弧的信息--------------\n"
for(k=0;
k<
G.arcnum;
k++)
{printf("
●●请输入第%d弧的两个起始顶点和其权值为:
k+1);
//输入一条边及依附的顶点及权值
for(;
;
){
%d%d%d"
v1,&
v2,&
weight);
if((v1>
0&
&
v1<
=G.vexnum)&
(v2>
v2<
=G.vexnum))
break;
else
printf("
输入有误,不存在该顶点,请重新输入^_^\n"
}
i=LocateVex(G.vexs,v1);
//找到两个结点在邻接矩阵中的位置
j=LocateVex(G.vexs,v2);
G.arcs[i][j]=weight;
//边的权值
G.arcs[j][i]=G.arcs[i][j];
//置(v1,v2)成(v2,v1)
-----------------------------------------------\n"
returnG;
本子函数是用来建立图,其中用到了邻接矩阵用以存储各边的权值以及判断是否连通,
其中所调用的LocateVex()是用来指出该顶点在邻接矩阵中所在的位置,其子函数定义如下:
intLocateVex(intvexs[],intv){//确定结点是否存在
intt;
for(inti=0;
MAX;
i++)
if(vexs[i]==v)
t=i;
returnt;
}
(2)使用Prim算法实现找出图中的最小生成树
voidMiniTree_PRIM(MGraphG,intu){
intk=u;
inti,j;
i++)//初始化closedge数组,v={u}
if(i!
=k)//两个顶点不重合
{closedge[i].adjvex=u+1;
//首先将u视为第一条边的第一个依附顶点
if(!
G.arcs[k][i])//两点之间不连通
closedge[i].lowcost=-1;
closedge[i].lowcost=G.arcs[k][i];
//调整closedge数组的最小代价lowcost为边上的权值
closedge[k].lowcost=0;
for(i=0;
G.vexnum-1;
i++){//★取其余G.vexnum-1个顶点,循环从此处开始,i无任何意义
j++)
if(closedge[j].lowcost>
0){//求出T的下一个结点,第K结点
k=j;
break;
0)
if(closedge[j].lowcost<
closedge[k].lowcost)//比较权值大小,从中找出权值最小的边
k=j;
%d----------------->
%d(%d)\n"
closedge[k].adjvex,G.vexs[k],closedge[k].lowcost);
//将此第k个顶点并入U集中
j++)////在顶点k并入U之后,更新closedge[i],新顶点并入U后重新选择最小边
if(G.arcs[k][j]>
0){
if(closedge[j].lowcost==-1){//如果先前时此两个顶点之间是不连通的
closedge[j].lowcost=G.arcs[k][j];
//新的权值域改成新加入顶点与该顶点的权值
closedge[j].adjvex=G.vexs[k];
else//如果此前两顶点本已连通
if(G.arcs[k][j]<
closedge[j].lowcost){//调整closedge数组中各边的最小权值
//依附于最小权值边在U中的顶点
//边的权值赋给closedge数组的最小权值域
}
}
}}
其中要说明的是其中使用了一个辅助数组,其定义如下:
structclosed{
intadjvex;
//依附于最小权值边在顶点集合U中的顶点
intlowcost;
//存储最小边的权值
};
此数组对PRIM中产生的顶点和边的权值进行临时存储的数组,因此结构体中设计两个变量,顶点名adjvex,边的权值lowcost。
定义次数组名为closedclosedge[MAX]
在用PRIM算法计算图的最小生成树过程中,这里是整个算法的核心之所在。
先要指定点u最为最小生成树的起点,并以次来构成最小生成树,子函数中用k来作为u的载体,同时它也是u在图中的位置,后对辅助数组closedge进行初始化,首先将u视为第一条边的第一个依附顶点,从零开始,所以u+1。
如果两点间不连通则给边的权值lowcost赋值-1;
否则将选择的边的权值adj赋给loecost,即将起存储在辅助数组中。
而后开始寻找下一个结点,进行边的权值的比较,选择出最小权值的边。
将该边的顶点和权值存储入辅助数组中,然后重新选择最小边,如此重复直至结束。
将在次过程中选择的边的顶点和权值全部存储进辅助数组中。
而后开始调整辅助数组中各个边的最小权值,在辅助数组中生成最小生成树。
最后将存储在辅助数组中的最小生成树输出。
其中,使用多个FOR的套嵌来实现最小权值边的选择。
数组在这过程中始终作为临时存储空间,将筛选出的边的信息存储着,最后将其输出来。
(3)可建立由五点构造的图如下
邻接矩阵
普利姆算法中closedge数组的变化
V
closedge
23456UV-U
Vex
Lowcost
V1V1V1
6151,2,34,5,6
Lowcost
V3V1V3V3
0
55641,32,4,5,6
Lowcost
V3V6V3
00
5261,3,62,4,5
V3V3
000
561,3,6,42,5
V2
0000
31,2,3,4,65
00000
1,2,3,4,5,6
最后以顶点1开始所生成的最小生成树如下:
(4)上机调试
通过调试分析,发现此程序中的closedge数组变化是一个难点,其中的数值变化时整个课程设计的关键,或多或少有点繁琐,不容易掌握清楚。
如果数据之间的类型不同,会引发数据间交换紊乱。
指针空间未分配而导致系统随机给出个错误数据。
地址相冲突导致的程序错误。
这些都没有语法错误但是在调试中将引起乱码,是个重要的问题,而且会频繁出现。
因此要多调试,思考以解决这些问题。
在寻找下一结点时,寻找到最小权值边,将其两端的顶点信息及变的权值存储到辅助树组中。
在设计解决这些问题的时候用多个for进行套嵌实现查找、判断。
因为本程序使用的是prim算法,for循环的使用套嵌较复杂,因此在设计时要理清思路。
时间、空间性能分析
根据程序中的循环语句可以判断出普利姆算法的时间复杂度为O(n2)。
算法和图中边的数目无关,因此普利姆算法适合于求稠密网的最小生成树。
因为在算法中运用了邻接矩阵的存储结构,在无向图中,邻接矩阵是对称的。
所以仅需要存储上三角(下三角)的元素,因此需要n(n+1)个存储空间。
四、调试分析
五、用户使用说明
使用本程序时先进行图的顶点数和边数的输入。
然后对各个顶点进行顶点信息的输入。
接着对各个边的起点、终点、权值进行输入。
然后是选择是否输出所建图的的邻接矩阵,若输入有错误时会有提示语句,并重新选择。
最后输出使n个城市连接最小的成本。
六、源代码
#include"
stdio.h"
stdlib.h"
malloc.h"
#defineMAX20
typedefstruct{
intvexs[MAX];
//顶点信息集合
intarcs[MAX][MAX];
//各边的权值
intvexnum;
//顶点数
intarcnum;
//边数
}MGraph;
closedclosedge[MAX];
voidmenu(){
\t\t\t\t【PRIM算法】\n"
\t\t\t★任意给定的网和起点★\n"
\t\t〓〓求解出所有的最小生成树〓〓\n"
voidLJ(MGraphG){
inti,j,t;
printf("
是否输出该图的邻接矩阵:
\n"
▼1-----------是\n"
▼0-----------否\n"
for(;
t);
if(t==1){
★★建立的邻接矩阵如下★★\n"
for(i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 构造 可以 城市 连接 最小 生成