最小生成树算法
C语言代码部分来自小甲鱼的《数据结构与算法》
最小生成树:一个有 n 个结点的连通图的生成树是原图的 极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。
最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出,它们考虑问题的出发点是:为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能的小。
普里姆算法是以某个顶点为起点,逐步找到每个顶点上最小权值的边来构建最小生成树。克鲁斯卡尔算法则换一种思路,从边出发,因为权值是在边上,所以直接去找最小权值的边来构建生成树。
区别:当边较多顶点较少时,用普里姆算法比较快;当边较少顶点较多时,用克鲁斯卡尔算法比较有优势
一、普里姆(Prim)算法
1.C语言代码
#include "math.h"
#include "stdio.h"
#define MAXVEX 50
typedef struct MGraph
{
char vex[MAXVEX]; // 顶点集合
int numVertexes; // 顶点数
int numedg; // 边数
int arc[MAXVEX][MAXVEX]; // 邻接矩阵
}MGraph;
//=============================================//
//=============================================//
//Prim算法生成最小生成树
void MiniSpanTree_Prim(MGraph G)
{
int min,i,j,k;
int adjvex[MAXVEX]; //保存相关顶点下标
int lowcost[MAXVEX]; //保存相关顶点间边的权值
lowcost[0]=0; //V0作为最小生成树的根开始遍历,权值为0(当走到哪里时,显示所有联结的边)
adjvex[0]=0; //V0第一个加入(这是路径)
//初始化操作
for(i=1;i<G.numVertexes;i++)
{
lowcost[i]=G.arc[0][i]; //将邻接矩阵第0行所有权值先加入数组
adjvex[i]=0; //初始化全部先为V0的下标
}
//真正构造最小生成树的过程
for(i=1;i<G.numVertexes;i++)
{
min=INFINITY; //初始化最小权值为不可能数值inf
j=1;
k=0;
//遍历全部顶点
while (j<G.numVertexes)
{
//找出lowcaost数组已存储的最小权值(查找最小可走边)
if(lowcost[j]!=0 && lowcost[j]<min)
{
min=lowcost[j];
k=j; //将发现的最小权值的下标存入k,以待使用。
}
j++;
}
//打印当前顶点边权值最小的边
printf("(%d,%d)",adjvex[k],k); //adjvex是路径
lowcost[k]=0; //将当前顶点的权值设置为0,表示此顶点已经完成任务,进行下一个顶点的遍历
//邻接矩阵k行逐个遍历全部顶点
for(j=1;j<G.numVertexes;j++)
{
if(lowcost!=0 && G.arc[k][j]<lowcost