任务描述
本关任务:图的存储结构为邻接表,要求编写函数利用普里姆(Prim)算法求图的最小生成树。
相关知识
不论图的存储结构为邻接矩阵还是邻接表,普里姆(Prim)算法思想是一致的,只是求图的最小生成树过程中具体操作不同,例如:用邻接矩阵存储图时,可以直接读取边的权值,用邻接表存储图时,需要定义一个函数读取边的权值。
int GetWeight(ALGraph g,VertexType a,VertexType b ) //获取权值
{ int pa,pb;
pa=LocateVex(g,a);
pb=LocateVex(g,b);
ArcNode* p;
p=g.vertices[pa].firstarc;
if(pa == pb)
return 0;
while(p!=NULL)
{ if( p->data.adjvex == pb)
return p->data.info;
else
p=p->nextarc;
}
return INFINITY;
}
编程要求
无向网G的存储结构为邻接表,编写函数利用普里姆(Prim)算法求图的最小生成树:
- void MiniSpanTree_PRIM(ALGraph G,VertexType u); // 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
测试说明
平台会对你编写的代码进行测试:
测试输入: 3
lt3.txt
0
输入说明: 第一行输入
3
,表示输入图的类型为无向网。 第二行输入文件名,该文件里保存了图的数据信息,内容如下: 5 8 0 1 2 3 4 0 1 1 0 2 3 0 3 4 0 4 7 1 2 2 2 3 5 2 4 8 3 4 6 第1行为图的顶点的个数n; 第2行为图的边的条数m; 第3行至第n+2行是n个顶点的数据; 第n+3行至第n+m+2行是m条边的数据;
第三行输入利用普里姆算法构造最小生成树的起点。
预期输出: 无向网
5个顶点:
0 1 2 3 4
8条弧(边):
0→4 :7 0→3 :4 0→2 :3 0→1 :1
1→2 :2 1→0 :1
2→4 :8 2→3 :5 2→1 :2 2→0 :3
3→4 :6 3→2 :5 3→0 :4
4→3 :6 4→2 :8 4→0 :7
用普里姆算法从g的第0个顶点出发输出最小生成树的各条边:
最小代价生成树的各条边为:
边(0,1),权值为1
边(1,2),权值为2
边(0,3),权值为4
边(3,4),权值为6
输出说明: 第一行输出图的类型。 第二行起输出图的顶点和边的数据信息。 最后分行输出从第1个顶点出发用普里姆算法构造的最小生成树的各条边。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include"ALGraph.h"
#define INFINITY 4270000
typedef int VRType;
typedef struct min
{ /* 记录从顶点集U到V-U的代价最小的边的辅助数组定义 */
VertexType adjvex;
VRType lowcost;
}minside[MAX_VERTEX_NUM];
int GetWeight(ALGraph G,VertexType a,VertexType b );//获取权值
int minimum(minside SZ,ALGraph G); // 求SZ.lowcost的最小正值,并返回其在SZ中的序号
void MiniSpanTree_PRIM(ALGraph G,VertexType u);// 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
int main()
{
ALGraph g;
int n;
CreateGraphF (g); // 利用数据文件创建无向图
Display(g); // 输出无向图
scanf("%d",&n);
printf("用普里姆算法从g的第%d个顶点出发输出最小生成树的各条边:\n",n);
MiniSpanTree_PRIM(g,g.vertices [n].data); // Prim算法从第1个顶点构造最小生成树
}
int GetWeight(ALGraph G,VertexType a,VertexType b )//获取权值
{ int pa,pb;
pa=LocateVex(G,a);
pb=LocateVex(G,b);
ArcNode* p;
p=G.vertices[pa].firstarc;
if(pa == pb)
return 0;
while(p!=NULL)
{ if( p->data.adjvex == pb)
return p->data.info;
else
p=p->nextarc;
}
return INFINITY;
}
int minimum(minside SZ,ALGraph G)
{ /* 求SZ.lowcost的最小正值,并返回其在SZ中的序号 */
int i=0,j,k,min;
while(!SZ[i].lowcost)
i++;
min=SZ[i].lowcost; /* 第一个不为0的值 */
k=i;
for(j=i+1;j<G.vexnum;j++)
if(SZ[j].lowcost>0 && min>SZ[j].lowcost) /* 找到新的大于0的最小值 */
{
min=SZ[j].lowcost;
k=j;
}
return k;
}
void MiniSpanTree_PRIM(ALGraph G,VertexType u)
{
// 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
/********** Begin **********/
int i,j,k;
minside closedge;
k=LocateVex(G,u);
for(j=0;j<G.vexnum;j++){
strcpy(closedge[j].adjvex,u);
closedge[j].lowcost=GetWeight(G,G.vertices[k].data,G.vertices[j].data);
}
closedge[k].lowcost=0;
printf("最小代价生成树的各条边为:\n");
for(i=1;i<G.vexnum;i++){
k=minimum(closedge,G);
printf("边(%s,%s),权值为%d\n",closedge[k].adjvex,G.vertices[k].data,closedge[k].lowcost);
closedge[k].lowcost=0;
for(j=0;j<G.vexnum;j++){
int m = GetWeight(G,G.vertices[k].data,G.vertices[j].data);
if(m!=INFINITY && m != 0 && m < closedge[j].lowcost){
strcpy(closedge[j].adjvex, G.vertices[k].data);
closedge[j].lowcost=GetWeight(G,G.vertices[k].data, G.vertices[j].data);
}
}
}
/********** End **********/
}