Otakar Boruvka
本文给出Boruvka算法的C#实现源代码。
Boruvka算法用于查找边加权图的最小生成树(MST),它早于Prim和Kruskal的算法,但仍然可以被认为是两者的关联。
一、Boruvka算法的历史
1926年,奥塔卡·博鲁夫卡(Otakar Boruvka)首次提出了一种求给定图的MST的方法。这在计算机出现之前就已经存在了,事实上,它被用来设计一个高效的配电系统。
Georges Sollin在1965年重新发现了它,并将其用于并行计算。
二、Boruvka算法的思路
该算法的核心思想是从一组树开始,每个顶点代表一棵孤立的树。然后,我们需要不断增加边,以减少孤立树的数量,直到我们有一个单一的连接树。
让我们通过一个示例图逐步了解这一点:
步骤0:创建一个图表;
步骤1:从一堆未连接的树开始(树的数量=顶点的数量);
步骤2:当存在未连接的树时,对于每个未连接的树:
(1)以较小的重量找到它的边缘
(2)添加此边以连接另一棵树
三、Boruvka算法的源代码
1、核心代码
using System;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{/// <summary>/// 图的连接边信息/// </summary>public class EdgeInfo{/// <summary>/// 起始节点编码(按一般教材习惯,1起步)/// </summary>public int Start { get; set; } = 0;/// <summary>/// 终点编码(按一般教材习惯,也从1起步)/// </summary>public int End { get; set; } = 0;/// <summary>/// 边的权值/// </summary>public int Weight { get; set; } = 0;/// <summary>/// 构造函数/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <param name="c"></param>public EdgeInfo(int a, int b, int c){this.Start = a;this.End = b;this.Weight = c;}}/// <summary>/// MST-Boruvka算法/// </summary>public static class Boruvka_Minium_Spaning_Tree{private static int[] Parent { get; set; } = null;private static int[] Minium { get; set; } = null;/// <summary>/// 计算最小生成树(MST)的最小代价及树信息/// </summary>/// <param name="graph">图信息(边列表)</param>/// <param name="tree">返回树信息(边的列表)</param>/// <returns></returns>public static int Execute(EdgeInfo[] graph, out List<int> tree){tree = new List<int>();// 计算最大节点编号int N = 0;for (int i = 0; i < graph.Length; i++){if (graph[i].Start > N) N = graph[i].Start;if (graph[i].End > N) N = graph[i].End;}Parent = new int[N + 1];for (int i = 1; i <= N; i++){Parent[i] = i;}Minium = new int[N + 1];int result = 0;int components = N;while (components > 1){for (int i = 1; i <= N; i++){Minium[i] = -1;}for (int i = 0; i < graph.Length; i++){if (Root(graph[i].Start) == Root(graph[i].End)){continue;}int r_v = Root(graph[i].Start);if (Minium[r_v] == -1 || graph[i].Weight < graph[Minium[r_v]].Weight){Minium[r_v] = i;}int r_u = Root(graph[i].End);if (Minium[r_u] == -1 || graph[i].Weight < graph[Minium[r_u]].Weight){Minium[r_u] = i;}}for (int i = 1; i <= N; i++){if (Minium[i] != -1){if (Merge(graph[Minium[i]].Start, graph[Minium[i]].End)){result += graph[Minium[i]].Weight;tree.Add(Minium[i]);components--;}}}}return result;}private static int Root(int v){if (Parent[v] == v){return v;}return Parent[v] = Root(Parent[v]);}private static bool Merge(int v, int u){v = Root(v);u = Root(u);if (v == u){return false;}Parent[v] = u;return true;}}
}
2、测试与显示
List<EdgeInfo> g = new List<EdgeInfo>();
g.Add(new EdgeInfo(1, 2, 6));
g.Add(new EdgeInfo(1, 3, 1));
g.Add(new EdgeInfo(1, 4, 4));
g.Add(new EdgeInfo(1, 5, 4));
g.Add(new EdgeInfo(2, 4, 2));
g.Add(new EdgeInfo(2, 5, 2));
g.Add(new EdgeInfo(3, 4, 8));int weight = Boruvka_Minium_Spaning_Tree.Execute(g.ToArray(), out List<int> path);
StringBuilder sb = new StringBuilder();
sb.AppendLine("The minium weight is: " + weight + "<br>");
sb.AppendLine("The minium tree is : <br>");
foreach (int idx in path)
{sb.AppendLine("("+g[idx].Start + " --- " + g[idx].End + ") weight = " + g[idx].Weight + "<br>");
}
webBrowser1.DocumentText = sb.ToString();
更多算法源代码将陆续发布,建议关注。
——————————————————————————————————————————
POWER BY TRUFFER.CN