最小生成树.docx
《最小生成树.docx》由会员分享,可在线阅读,更多相关《最小生成树.docx(11页珍藏版)》请在冰豆网上搜索。
最小生成树
最小生成树问题
【问题描述】
若要在n个城市之间建设通信网络,只需要假设n-1条线路即可。
如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题。
【系统要求】
1.利用克鲁斯卡尔算法求网的最小生成树。
2.利用普里姆算法求网的最小生成树。
3.要求输出各条边及它们的权值。
【程序结构图】
【算法分析】
1.普里姆算法
voidMiniSpanTree_PRIM(MGraphG,intu)
{//下面用普里姆算法来实现
minsideclosedge;
inti,j,k;
k=LocateVex(G,u);
for(j=0;j{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j].adj;//引入了一个新的辅助数组,
}
printf("它的最小生成树权值和路径为\n");
for(i=1;i{
k=f(closedge,G);
printf("%d%d--%d\n",closedge[k].lowcost,closedge[k].adjvex,G.vexs[k]);//输出结果
closedge[k].lowcost=0;
for(j=1;j{
if(G.arcs[k][j].adj{
closedge[j].adjvex=G.vexs[k];
closedge[j].lowcost=G.arcs[k][j].adj;
//这一步是更新closedge的值
}
}
}
}
2.克鲁斯卡尔算法
voidKruskal(MGraph&G)
{
memset(fa,-1,sizeof(fa));
//初始化fa数组
intcnt=0;
for(intk=0;k{
intu=edge[k].from;
intv=edge[k].to;
intt1=find(u);//找第一个点的起始点
intt2=find(v);//找第二个点的起始点
if(t1!
=t2)
{//如果不相等,则不构成回路
fa[t1]=t2;
id[cnt]=k;
cnt++;
if(cnt==G.vexnum-1)//当已选了n-1条边时,退出循环
break;
}
}
printf("最小生成树的权值和边分别是:
\n");
for(intk=0;k{
intt=id[k];
printf("%d%d--%d\n",edge[t].len,edge[t].from,edge[t].to);
}
}
【程序测试】
建立如下图所示的城市网络:
测试结果截图:
【源代码】
#include
#include
#include
#include
usingnamespacestd;
#defineMAXN1005//假设点数不超过
#defineINFINITY32767
#defineOK1
#defineERROR0
#defineOVERFLOW0
#defineMAX_VERTEX_NUM20
intfa[MAXN];
intid[MAXN];
structEdge
{//边的数据结构
intfrom,to;
intlen;
};
Edgeedge[MAXN*MAXN];
boolcmp(Edgel,Edger)
{//边的比较函数
returnl.len}
intfind(intx)
{//并查集,用于判断是否与已选择的边构成环
if(fa[x]==-1)
returnx;
else
returnfa[x]=find(fa[x]);
}
typedefintVRType;
typedefintVertexType;
typedefstructArcCell
{VRTypeadj;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//定义的顶点的关系类型,代表不相邻1代表相邻
typedefstruct
{
VertexTypeadjvex;//abcdef
VRTypelowcost;//15488
}minside[100],mini;
typedefstruct
{AdjMatrixarcs;//一个邻接矩阵
VertexTypevexs[MAX_VERTEX_NUM];
//每个顶点的弧
intvexnum,arcnum;//图的当前顶点数和弧数
}MGraph;//定义了图的结构
intLocateVex(MGraphG,VertexTypeu)
{
inti;
for(i=0;i{
if(u==G.vexs[i])
returni;
}
return-1;
}
intf(miniclosedge[100],MGraphG)
{
inti=0,k,j,min;
while(!
closedge[i].lowcost)
i++;
min=closedge[i].lowcost;
k=i;
for(j=i+1;jif(closedge[j].lowcost>0&&min>closedge[j].lowcost)
{
min=closedge[j].lowcost;
k=j;
}
returnk;
}//找到非零该行最小的元素
voidreadin(MGraph&G)
{
intr=0;
intl=0;
intw=0;
inti,j,k;
printf("请您输入所建图的顶点数、弧数\n");
scanf("%d%d",&G.vexnum,&G.arcnum);
//getchar();
printf("请您依次输入各个顶点:
\n");
for(i=0;i{
scanf("%d",&G.vexs[i]);
//getchar();//输入每个节点的值
}
for(i=0;ifor(j=0;jG.arcs[i][j].adj=32767;
//将每一个节点的值都设为无穷大
printf("请输入顶点,弧,权值:
\n");
for(k=0;k{
scanf("%d%d%d",&l,&r,&w);
edge[k].from=min(l,r);
edge[k].to=max(l,r);
edge[k].len=w;
i=LocateVex(G,l);
j=LocateVex(G,r);
G.arcs[i][j].adj=G.arcs[j][i].adj=w;//赋值的工作
}
sort(edge,edge+G.arcnum,cmp);
return;
}
voidKruskal(MGraph&G)
{
memset(fa,-1,sizeof(fa));
//初始化fa数组
intcnt=0;
for(intk=0;k{
intu=edge[k].from;
intv=edge[k].to;
intt1=find(u);//找第一个点的起始点
intt2=find(v);//找第二个点的起始点
if(t1!
=t2)
{//如果不相等,则不构成回路
fa[t1]=t2;
id[cnt]=k;
cnt++;
if(cnt==G.vexnum-1)//当已选了n-1条边时,退出循环
break;
}
}
printf("最小生成树的权值和边分别是:
\n");
for(intk=0;k{
intt=id[k];
printf("%d%d--%d\n",edge[t].len,edge[t].from,edge[t].to);
}
}
voidMiniSpanTree_PRIM(MGraphG,intu)
{//下面用普里姆算法来实现
minsideclosedge;
inti,j,k;
k=LocateVex(G,u);
for(j=0;j{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j].adj;//引入了一个新的辅助数组,
}
printf("它的最小生成树权值和路径为\n");
for(i=1;i{
k=f(closedge,G);
printf("%d%d--%d\n",closedge[k].lowcost,closedge[k].adjvex,G.vexs[k]);//输出结果
closedge[k].lowcost=0;
for(j=1;j{
if(G.arcs[k][j].adj{
closedge[j].adjvex=G.vexs[k];
closedge[j].lowcost=G.arcs[k][j].adj;
//这一步是更新closedge的值
}
}
}
}
intmain()
{
intn;
do{
printf("\t\t\t主菜单\n");
printf("\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("\t\t\t1.创建城市通讯网\n");
printf("\t\t\t2.克鲁斯卡尔算法求最短路径\n");
printf("\t\t\t3.普里姆算法求最短路径\n");
printf("\t\t\t4.退出\n");
printf("\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("请输入序号选择相应操作:
");
scanf("%d",&n);
switch(n)
{
case1:
MGraphG;readin(G);break;
case2:
Kruskal(G);break;
case3:
MiniSpanTree_PRIM(G,G.vexs[0]);break;
case4:
printf("欢迎使用\n");break;
default:
printf("输入错误");
}
}while(n!
=4);
}