Prim算法生成最小生成树
1. 问题
最小生成树:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边
2. 解析
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得的 w(T) 最小,则此 T 为 G 的最小生成树。
Prim算法: Prim算法构建最小生成树的过程是:先构建一棵只包含根结点V1的树A,然后每次在连接树A结点和图G中树A以外的结点的所有边中,选取一条权重最小的边加入树A,直至树A覆盖图G中的所有结点。
注意:
(1)每次都选取权值最小的边,但不能构成回路,构成环路的边则舍弃。
(2)遇到权值相等,又均不构成回路的边,随意选择哪一条,均不影响生成树结果。
(3)选取n-1条恰当的边以连通n个顶点。
3. 设计
[核心伪代码]
4. 分析
算法步骤执行O(n)次 时间复杂度T(n)=O(n)
5. 源码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAX 100000
#define VNUM 10+1 /*?啥意思*/
int edge[VNUM][VNUM] = {/*输入邻阶矩阵*/ };
int lowcost[VNUM] = { 0 };
int addvnew[VNUM];
int adjecent[VNUM] = { 0 };
void prim(int start) {
int sumweigth = 0;
int i, j, k = 0;
for (i = 1; i < VNUM; ++i) {//从顶点1开始
lowcost[i] = edge[start][i];
addvnew[i] = 1;
}
addvnew[start] = 0;//将起始点start加入VNUM
adjecent[start] = start;
for (i = 1; i < VNUM - 1; ++i) {
int min = MAX;
int v = -1;
for (j = 1; j < VNUM; ++j) {
if (addvnew[j] != -1 && lowcost[j] < min) {
min = lowcost[j];
v = j;
}
}
if (v != -1) {
printf("%d %d %d\n", adjecent[v], v, lowcost[v]);
addvnew[v] = 0;
sumweigth += lowcost[v];//计算路径长度的和
for (j = 1; j < VNUM; ++j) {
if (addvnew[j] == -1 && edge[v][j] < lowcost[j]) {
lowcost[j] = edge[v][j];
adjecent[j] = v;
}
}
}
}
printf("最小的权值为 %d",sumweigth);
}