数据结构—图的操作与应用—第8关:求图(邻接表存储)最小生成树的普里姆(Prim)算法


任务描述

本关任务:图的存储结构为邻接表,要求编写函数利用普里姆(Prim)算法求图的最小生成树。

相关知识

不论图的存储结构为邻接矩阵还是邻接表,普里姆(Prim)算法思想是一致的,只是求图的最小生成树过程中具体操作不同,例如:用邻接矩阵存储图时,可以直接读取边的权值,用邻接表存储图时,需要定义一个函数读取边的权值。

 
  1. int GetWeight(ALGraph g,VertexType a,VertexType b ) //获取权值
  2. { int pa,pb;
  3. pa=LocateVex(g,a);
  4. pb=LocateVex(g,b);
  5. ArcNode* p;
  6. p=g.vertices[pa].firstarc;
  7. if(pa == pb)
  8. return 0;
  9. while(p!=NULL)
  10. { if( p->data.adjvex == pb)
  11. return p->data.info;
  12. else
  13. p=p->nextarc;
  14. }
  15. return INFINITY;
  16. }

编程要求

无向网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 **********/
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值