- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐近分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈与队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 散列表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树遍历
- DSA - 二叉搜索树
- DSA - AVL树
- DSA - 红黑树
- DSA - B树
- DSA - B+树
- DSA - 伸展树
- DSA - 字典树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 使用递归实现汉诺塔
- DSA - 使用递归实现斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大最小问题
- DSA - Strassen矩阵乘法
- DSA - Karatsuba算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - 普里姆最小生成树
- DSA - 克鲁斯卡尔最小生成树
- DSA - Dijkstra最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止时间的作业排序
- DSA - 最优合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall算法
- DSA - 0-1背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似算法)
- 随机算法
- DSA - 随机算法
- DSA - 随机快速排序算法
- DSA - Karger最小割算法
- DSA - Fisher-Yates洗牌算法
- DSA有用资源
- DSA - 问答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
克鲁斯卡尔最小生成树算法
克鲁斯卡尔最小生成树算法是寻找图的最小生成树的有效方法之一。最小生成树是一个子图,它以最少的边和最小成本(分配给每条边的权重之和)连接主图中的所有顶点。
该算法首先从图的森林开始——定义为仅包含主图顶点的子图——然后添加成本最低的边,直到创建最小生成树,而不会在图中形成环。
克鲁斯卡尔算法比普里姆算法更容易实现,但复杂度更高。
克鲁斯卡尔算法
克鲁斯卡尔算法的输入是图 G {V, E},其中 V 是顶点集,E 是边集,以及源顶点 S,输出是图 G 的最小生成树。
算法
将图中所有边按升序排序,并将其存储在数组edge[] 中。
在平面上构造图的森林,其中包含所有顶点。
从edge[]数组中选择成本最低的边,并将其添加到图的森林中。通过将访问过的顶点添加到visited[]数组中来标记已访问的顶点。
重复步骤2和3,直到所有顶点都被访问,并且图中没有形成任何环。
当所有顶点都被访问时,最小生成树就形成了。
计算形成的输出生成树的最小成本。
示例
使用克鲁斯卡尔算法为下面给出的图构造最小生成树:
解决方案
第一步,将给定图中的所有边按升序排序,并将值存储在数组中。
边 | B→D | A→B | C→F | F→E | B→C | G→F | A→G | C→D | D→E | C→G |
---|---|---|---|---|---|---|---|---|---|---|
成本 | 5 | 6 | 9 | 10 | 11 | 12 | 15 | 17 | 22 | 25 |
然后,在一个平面上构造给定图的森林。
从排序的边成本列表中,选择成本最低的边,并将其添加到输出图的森林中。
B → D = 5 Minimum cost = 5 Visited array, v = {B, D}
类似地,下一个成本最低的边是 B → A = 6;因此,我们将其添加到输出图中。
Minimum cost = 5 + 6 = 11 Visited array, v = {B, D, A}
下一个成本最低的边是 C → F = 9;将其添加到输出图中。
Minimum Cost = 5 + 6 + 9 = 20 Visited array, v = {B, D, A, C, F}
下一个要添加到输出图的边是 F → E = 10。
Minimum Cost = 5 + 6 + 9 + 10 = 30 Visited array, v = {B, D, A, C, F, E}
来自成本最低数组的下一条边是 B → C = 11,因此我们将其添加到输出图中。
Minimum cost = 5 + 6 + 9 + 10 + 11 = 41 Visited array, v = {B, D, A, C, F, E}
要添加到输出图的来自成本最低数组的最后一条边是 F → G = 12。
Minimum cost = 5 + 6 + 9 + 10 + 11 + 12 = 53 Visited array, v = {B, D, A, C, F, E, G}
获得的结果是给定图的最小生成树,成本 = 53。
示例
最终程序实现了克鲁斯卡尔最小生成树问题,该问题将成本邻接矩阵作为输入,并打印最短路径以及最小成本作为输出。
#include <stdio.h> #include <stdlib.h> const int inf = 999999; int k, a, b, u, v, n, ne = 1; int mincost = 0; int cost[3][3] = {{0, 10, 20},{12, 0,15},{16, 18, 0}}; int p[9] = {0}; int applyfind(int i) { while(p[i] != 0) i=p[i]; return i; } int applyunion(int i,int j) { if(i!=j) { p[j]=i; return 1; } return 0; } int main() { n = 3; int i, j; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (cost[i][j] == 0) { cost[i][j] = inf; } } } printf("Minimum Cost Spanning Tree: \n"); while(ne < n) { int min_val = inf; for(i=0; i<n; i++) { for(j=0; j <n; j++) { if(cost[i][j] < min_val) { min_val = cost[i][j]; a = u = i; b = v = j; } } } u = applyfind(u); v = applyfind(v); if(applyunion(u, v) != 0) { printf("%d -> %d\n", a, b); mincost +=min_val; } cost[a][b] = cost[b][a] = 999; ne++; } printf("Minimum cost = %d",mincost); return 0; }
输出
Minimum Cost Spanning Tree: 0 -> 1 1 -> 2 Minimum cost = 25
#include <iostream> using namespace std; const int inf = 999999; int k, a, b, u, v, n, ne = 1; int mincost = 0; int cost[3][3] = {{0, 10, 20}, {12, 0, 15}, {16, 18, 0}}; int p[9] = {0}; int applyfind(int i) { while (p[i] != 0) { i = p[i]; } return i; } int applyunion(int i, int j) { if (i != j) { p[j] = i; return 1; } return 0; } int main() { n = 3; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (cost[i][j] == 0) { cost[i][j] = inf; } } } cout << "Minimum Cost Spanning Tree:\n"; while (ne < n) { int min_val = inf; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (cost[i][j] < min_val) { min_val = cost[i][j]; a = u = i; b = v = j; } } } u = applyfind(u); v = applyfind(v); if (applyunion(u, v) != 0) { cout << a << " -> " << b << "\n"; mincost += min_val; } cost[a][b] = cost[b][a] = 999; ne++; } cout << "Minimum cost = " << mincost << endl; return 0; }
输出
Minimum Cost Spanning Tree: 0 -> 1 1 -> 2 Minimum cost = 25
import java.util.*; public class Main { static int k, a, b, u, v, n, ne = 1, min, mincost = 0; static int cost[][] = {{0, 10, 20},{12, 0, 15},{16, 18, 0}}; static int p[] = new int[9]; static int inf = 999999; static int applyfind(int i) { while(p[i] != 0) i=p[i]; return i; } static int applyunion(int i,int j) { if(i!=j) { p[j]=i; return 1; } return 0; } public static void main(String args[]) { int i, j; n = 3; for(i=0; i<n; i++) for(j=0; j<n; j++) { if(cost[i][j]==0) cost[i][j]= inf; } System.out.println("Minimum Cost Spanning Tree: "); while(ne < n) { min = inf; for(i=0; i<n; i++) { for(j=0; j<n; j++) { if(cost[i][j] < min) { min=cost[i][j]; a=u=i; b=v=j; } } } u=applyfind(u); v=applyfind(v); if(applyunion(u,v) != 0) { System.out.println(a + " -> " + b); mincost += min; } cost[a][b]=cost[b][a]=999; ne +=1; } System.out.println("Minimum cost = " + mincost); } }
输出
Minimum Cost Spanning Tree: 0 -> 1 1 -> 2 Minimum cost = 25
inf = 999999 k, a, b, u, v, n, ne = 0, 0, 0, 0, 0, 0, 1 mincost = 0 cost = [[0, 10, 20], [12, 0, 15], [16, 18, 0]] p = [0] * 9 def applyfind(i): while p[i] != 0: i = p[i] return i def applyunion(i, j): if i != j: p[j] = i return 1 return 0 n = 3 for i in range(n): for j in range(n): if cost[i][j] == 0: cost[i][j] = inf print("Minimum Cost Spanning Tree:") while ne < n: min_val = inf for i in range(n): for j in range(n): if cost[i][j] < min_val: min_val = cost[i][j] a = u = i b = v = j u = applyfind(u) v = applyfind(v) if applyunion(u, v) != 0: print(f"{a} -> {b}") mincost += min_val cost[a][b] = cost[b][a] = 999 ne += 1 print(f"Minimum cost = {mincost}")
输出
Minimum Cost Spanning Tree: 0 -> 1 1 -> 2 Minimum cost = 25