5.1 最小生成树
-
定义
对一个带权连通无向图G=(V,E)G=(V,E)G=(V,E),生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。
设R为G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称为G的最小生成树(MST)。
-
性质
1.最小生成树可能有多个,但边的权值之和总是唯一且最小的;
2.最小生成树的边数=顶点数-1。砍掉一条则不连通,增加一条会出现回路;
3.如果一个连通图本身就是一棵树,则其最小生成树就是它本身;
4.只有连通图才有最小生成树,非连通图只有生成森林。
5.1.1 Prim算法
-
定义
从某一个顶点开始构建生成树;
每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止。

- 即选最小权值的结点
-
时间复杂度
O(∣V∣2)O(|V|^2)O(∣V∣2),适用于稠密图(|E|大的)。
-
算法的实现思想
-
思路:
从V0V_0V0开始,总共需要n-1轮处理。
第一轮处理:循环遍历所有个结点,找到
lowCast最低的,且还没加入树的顶点。再次循环遍历,更新还没加入的各个顶点的
lowCast值。 -
代码步骤:
1.创建
isJoin数组,初始为false,判断结点是否加入树。2.创建
lowCost数组,用于存储到该结点的最短距离。3.从v0v_0v0开始,将与其连接的权值加入到
lowCost数组中。4.遍历
lowCast数组,找到最小值,将其加入树中,并继续遍历与其相连的边。
-
5.1.2 Kruskal算法
-
定义
每次选则一条权值最小的边,使这条边的两头连通(原本已经连通的不选),直到所有结点都连通。

- 即每次选最小的边
-
时间复杂度
O(∣E∣log2∣E∣)O(|E|log_2|E|)O(∣E∣log2∣E∣),适用于边稀疏图。
-
算法的实现思想
-
思路:
初始:将各条边按权值排序。
共执行e轮,每轮判断两个顶点是否属于同一集合,需要O(log2e)O(log_2e)O(log2e)
-
5.1.3 最小生成树代码
A.邻接矩阵
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#define V 5 // 图的顶点数
// 找到距离集合最近的顶点
int min_key(int key[], bool mst_set[]) {
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++) {
if (mst_set[v] == false && key[v] < min) {
min = key[v];
min_index = v;
}
}
return min_index;
}
// 打印最小生成树
void print_mst(int parent[], int graph[V][V]) {
printf("Edge Weight\n");
for (int i = 1; i < V; i++)
printf("%d - %d %d \n", parent[i], i, graph[i][parent[i]]);
}
// Prim算法
void prim_mst(int graph[V][V]) {
int parent[V]; // 存放最小生成树的父节点
int lowCost[V]; // 用于存放顶点到最小生成树的最小权重
bool isJoin[V]; // 记录顶点是否已经加入最小生成树
for (int i = 0; i < V; i++) {

解析+完整代码&spm=1001.2101.3001.5002&articleId=138292702&d=1&t=3&u=fee638717d5047a09bec30e04d130a0c)
4万+

被折叠的 条评论
为什么被折叠?



