最小生成树(普里姆算法)

本文详细介绍了如何使用普里姆算法从给定的图中构造最小生成树,并提供了完整的代码实现。普里姆算法是一种用于寻找无向图中权重最小的树形子图的方法,适用于解决实际问题中的网络连接最小成本问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <limits.h>//
#define INFINITY  INT_MAX//用整型最大值代替无穷大
#define MAX_VERTEX_NUM 20//最大的顶点的个数
#define MAX_NAME 3//定点字符串的最大长度+1
typedef int VRType;
typedef char VertexType[MAX_NAME];
typedef char InfoType;
//-------图的数组(邻接矩阵)存储表示-------
typedef enum
{
DG,DN,UDG,UDN//有向图,有向网,无向图,无向网
}GraphKind;
typedef struct ArcCell
{
  VRType adj;// VRType是顶点关系类型,对无全图,用0或1,表示相邻否
             //对带权图,则为权值类型
  InfoType *info;//该弧的相关信息
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
  VertexType vexs[MAX_VERTEX_NUM];//定点向量
  AdjMatrix arcs;//邻接矩阵
  int vexnum,arcnum;//图的当前定点数和弧数
  GraphKind kind;//图的种类标志
}MGraph;
//记录从顶点U到v-U的代价最小的边的辅助数组定义
typedef struct
{
  VertexType adjvex;
  VRType lowcost;
}closedge[MAX_VERTEX_NUM];
//查询某个顶点的位置函数
int LocateVex(MGraph G,VertexType u)//此处u为顶点
{
  int i;
  for(i=0;i<G.vexnum;i++)
  {
	  if(strcmp(u,G.vexs[i])==0)
		  return i;
  }
 if(i==G.vexnum)
 {
	 printf("不存在该顶点!\n");
     exit(1); 
 }
 return 0;
}
//创建有向网
void CreatGraph(MGraph &G)
{
  int i,j,k,adj;
  char ch;
  VertexType  v1,v2;
  printf("请输入要创建的图的顶点的个数和边的个数(以空格隔开):");
  scanf("%d%d",&G.vexnum,&G.arcnum);
  ch=getchar();//吸收回车符
  printf("请输入顶点的值:\n");
  for(i=0;i<G.vexnum;i++)
  {
    scanf("%s",&G.vexs[i]);//输入顶点的值
	ch=getchar();
  }
  for(i=0;i<G.vexnum;i++)//先对整个邻接矩阵进行初始化
	  for(j=0;j<G.vexnum;j++)
	  {
	     G.arcs[i][j].adj=INFINITY;//权值为最大值
		 G.arcs[i][j].info=NULL;//顶点信息为空
	  }
  printf("请输入图的弧的相关信息(v1,v2,adj即顶点1,顶点2,权值):\n");
 for(k=0;k<G.arcnum;k++)//再根据输入的弧来更新邻接矩阵
 {
   scanf("%s%s%d",&v1,&v2,&adj);
   ch=getchar();
   i=LocateVex(G,v1);//找到顶点v1和v2的下表位置
   j=LocateVex(G,v2);
   G.arcs[i][j].adj=adj;//更新有关联的顶点的权值
 }	 
}
//显示图的函数
void display(MGraph G)
{
   int i,j;
   if(G.vexnum==0)
	   printf("该图是个空图!\n");
   for(i=0;i<G.vexnum;i++)
   {
	   for(j=0;j<G.vexnum;j++)
	   {
	     printf("%d  ",G.arcs[i][j].adj);
	   }
	   printf("\n");
   }
}
//查询当前closedge.lowcost中最小的值
int minmum(closedge &S,MGraph G)
{
 
	int i=0,j,k,min;
   while(!S[i].lowcost)//不为0 的情况下
	   i++;
   k=i;
   min=S[i].lowcost;
   for(j=i+1;j<G.vexnum;j++)
   {
	   if(S[j].lowcost>0)
	   {
          if(min>S[j].lowcost)
		  {
		       k=j;
			   min=S[j].lowcost;
		  }
		  
	   }
   }
   return k;
}

//用普里姆算法从第u个顶点除法构造网G的最小生成树T,输出T的各条边
void MiniSpanTree_PRIM(MGraph G,VertexType u)
{
  closedge min;
  int k,j,i;
  k=LocateVex(G,u);
  for(j=0;j<G.vexnum;j++)//辅助数组初始化
  {
    if(j!=k) 
	{
	  strcpy(min[j].adjvex,G.vexs[k]);	
	  min[j].lowcost=G.arcs[k][j].adj;
	}
  }
  min[k].lowcost=0;//初始,U={u};
  for(j=1;j<G.vexnum;j++)
  {
    k=minmum(min,G);//选择其余G.vexnum-1个顶点中与U集合中关联的权值最小的顶点
	printf("%s--%s\n",min[k].adjvex,G.vexs[k]);//输出生成树的边
	min[k].lowcost=0;//第k个顶点加入集合U
	for(i=0;i<G.vexnum;i++)//对辅助数组的重新更新
	{
	  if(G.arcs[k][i].adj<min[i].lowcost)
	  {
	    strcpy(min[i].adjvex,G.vexs[k]);	
	    min[i].lowcost=G.arcs[k][i].adj;
	  }
		  
	}
  }
}
int main()
{
   MGraph G;
   CreatGraph(G);//创建图
   display(G);//显示图
   MiniSpanTree_PRIM(G,G.vexs[0]);//普里姆算法求最小生成树
   
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值