普里姆算法构造最小生成树

本文详细介绍了使用普里姆算法求解图的最小生成树的过程,包括邻接矩阵的构建、查找节点位置、初始化权值数组以及算法的具体步骤。通过示例展示了如何从输入的顶点和边构建图,然后应用普里姆算法找到最小生成树,并输出树的边及总权值。

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

/* 普利姆算法求解最小生成树,它有两个集合,已选点构成一个集合,未被选出的点都成那个一个集合
需要三个辅助的数组,adjvex[n]储存边的起点  
lowcost[n]用来储存选出边的权值,vexs[n]用来储存终结点 ,他们需要 一一对应 ,起初所有节点的
间的权值都为无穷大,选出一个起始节点,把它的临结点的所有边的权值,按照顺序存入数组vexs,起始节点存放入adjex,
(根据邻接矩阵,如果它是第j行第 i列,就把边的权值存放在loecost[i]中,权值,起始点,和终点存入数组的下标一致),
然后选出和起始节点相连接的权值最小的临结点,输出对应的起点和终点,然后让这个边的权值变为无穷大,表示已经选出该边 
然后这个点的所有边的权值记录到数组lowcost[n]中 ,把这个结点值存入到adjvex[n],然后重复此步骤,选出n-1条边。 
*/ 
#include <stdio.h>
#include<iostream>
#include <string.h>
#define maxint 32726
#define  maxvex 100
#define max 100
int sum=0;
using namespace std;
typedef struct{
	char vexs[maxvex];
	int arcs[maxvex][maxvex];
	int vexnum,arcnum;
}Amg;

  //邻接矩阵查找节点的位置 
 int locate(char vexs[] , char vex,int n){
 	  int i,j;
 	  for(i=1;i<=n;i++){
 	  	if(vexs[i]==vex){
 	  		j=i;
		   }
	   }
	   return j;
 } 
 //用邻接矩阵建立图 
void Creat1UND(Amg &G){
	char v1,v2;//两个顶点的值 
	int w;//边的权值 
	int q,e;//顶点的坐标 
	printf("请输入顶点数和边数:");
	cin>>G.vexnum>>G.arcnum;
	printf("请输入各顶点的值:\n"); 
	for(int i=1;i<=G.vexnum;i++){
		cin>>G.vexs[i];
	}
	for(int i=1;i<=G.vexnum;i++){
		for(int j=1;j<=G.vexnum;j++){
			G.arcs[i][j]=maxint;
		}
	}
	printf("请输入两个顶点以及权值;\n");
	for(int k=1;k<=G.arcnum;++k){
	  cin>>v1>>v2>>w; 
	  q=locate(G.vexs,v1,G.vexnum);
	  e=locate(G.vexs,v2,G.vexnum);
	  G.arcs[q][e]=w;
	}
	for(int i=1;i<=G.vexnum;i++){
		for(int j=1;j<=G.vexnum;j++){
				printf("%-10d  ",G.arcs[i][j]) ;
			}
			printf("\n");
		}
	
}
//普里姆算法求最小生成树
void Minitree(Amg &G,char u){
     char adjvex[G.vexnum+1]={0};//记录起始点的数组 
      int lowcost[G.vexnum+1];//储存权值 
      for(int i=1;i<=G.vexnum;i++){//起初所有节点都没选出,权值都为无穷 
      	lowcost[i]=maxint ;
	  }
      int min=maxint;//用来比较的值 
      int m,b=locate(G.vexs,u,G.vexnum); //找出第一个结点的下标 
      lowcost[b]=maxint ;
      for(int i=1;i<=G.vexnum;i++){//把它的所有临结点的权值存入lowcost中 
      	if(G.arcs[b][i]<maxint){
      		adjvex[i]=G.vexs[b];//对应边的起始点 
      		lowcost[i]=G.arcs[b][i];
		  }
	  }
      for(int i=1;i<G.vexnum;i++){//n-1 次循环 
           for(int j=1;j<=G.vexnum;j++){
           	if(lowcost[j]<min){//找出最小边的权值 
           		min=lowcost[j];
           		m=j;
			   }
	}
		   sum+=min;//记录权值 
		   printf("最小生成树为:"); 
		 printf("<%c %c> ",adjvex[m],G.vexs[m]);//输出这个边 
		 
		 lowcost[m]=maxint;//将选出边的权值改为无穷 
		 min=maxint;//更新最小值
	for(int k=1;k<=G.vexnum;k++){
      	if(G.arcs[m][k]<maxint){//将选出新的结点的所有临结点的权值进入数组中,并还有对应的起始点 
		  	adjvex[k]=G.vexs[m]; 
      		lowcost[k]=G.arcs[m][k];
		  }
	  } 
	  }
	  printf("权值和为:%d",sum); 
}
/*
输入结点数 6 边数 10
各个结点和权值 
1 3 1
3 4 5
1 4 5
1 2 5
2 3 5
2 5 3
5 3 6
5 6 6
6 4 2
3 6 4
*/
int main(){
	char b;
	Amg G;
	Creat1UND(G);
	cin>>b;
	Minitree(G, b);
	return 0; 
	
}
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值