关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 算法设计 »Kruskal 最小生成树算法

    Kruskal 最小生成树算法

    2015-02-01 00:00:00 出处:企鹅大数据
    分享

    对于一个给定的连通的无向图 G = (V, E),希望找到一个无回路的子集 T,T 是 E 的子集,它连接了所有的顶点,且其权值之和为最小。

    因为 T 无回路且连接所有的顶点,所以它必然是一棵树,称为生成树(Spanning Tree),因为它生成了图 G。显然,由于树 T 连接了所有的顶点,所以树 T 有 V – 1 条边。一张图 G 可以有很多棵生成树,而把确定权值最小的树 T 的问题称为最小生成树问题(Minimum Spanning Tree)。术语 “最小生成树” 实际上是 “最小权值生成树” 的缩写。

    Kruskal 算法提供一种在 O(ElogV) 运行时间确定最小生成树的方案。Kruskal 算法基于贪心算法(Greedy Algorithm)的思想进行设计,其选择的贪心策略就是,每次都选择权重最小的但未形成环路的边加入到生成树中。其算法结构如下:

    将所有的边按照权重非递减排序; 选择最小权重的边,判断是否其在当前的生成树中形成了一个环路。假如环路没有形成,则将该边加入树中,否则放弃。 重复步骤 2,直到有 V – 1 条边在生成树中。

    上述步骤 2 中使用了 Union-Find 算法来判断是否存在环路。

    例如,下面是一个无向连通图 G。

    图 G 中包含 9 个顶点和 14 条边,所以期待的最小生成树应包含 (9 – 1) = 8 条边。

    首先对所有的边按照权重的非递减顺序排序:

    Weight Src Dest
    1 7 6
    2 8 2
    2 6 5
    4 0 1
    4 2 5
    6 8 6
    7 2 3
    7 7 8
    8 0 7
    8 1 2
    9 3 4
    10 5 4
    11 1 7
    14 3 5

    然后从排序后的列表中选择权重最小的边。

    1. 选择边 {7, 6},无环路形成,包含在生成树中。

    2. 选择边 {8, 2},无环路形成,包含在生成树中。

    3. 选择边 {6, 5},无环路形成,包含在生成树中。

    4. 选择边 {0, 1},无环路形成,包含在生成树中。

    5. 选择边 {2, 5},无环路形成,包含在生成树中。

    6. 选择边 {8, 6},有环路形成,放弃。

    7. 选择边 {2, 3},无环路形成,包含在生成树中。

    8. 选择边 {7, 8},有环路形成,放弃。

    9. 选择边 {0, 7},无环路形成,包含在生成树中。

    10. 选择边 {1, 2},有环路形成,放弃。

    11. 选择边 {3, 4},无环路形成,包含在生成树中。

    12. 由于当前生成树中已经包含 V – 1 条边,算法结束。

    C# 实现的 Kruskal 算法如下。

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 
      5 namespace GraphAlgorithmTesting
      6 {
      7   class Program
      8   {
      9     static void Main(string[] args)
     10     {
     11       Graph g = new Graph(9);
     12       g.AddEdge(0, 1, 4);
     13       g.AddEdge(0, 7, 8);
     14       g.AddEdge(1, 2, 8);
     15       g.AddEdge(1, 7, 11);
     16       g.AddEdge(2, 3, 7);
     17       g.AddEdge(2, 5, 4);
     18       g.AddEdge(8, 2, 2);
     19       g.AddEdge(3, 4, 9);
     20       g.AddEdge(3, 5, 14);
     21       g.AddEdge(5, 4, 10);
     22       g.AddEdge(6, 5, 2);
     23       g.AddEdge(8, 6, 6);
     24       g.AddEdge(7, 6, 1);
     25       g.AddEdge(7, 8, 7);
     26 
     27       Console.WriteLine();
     28       Console.WriteLine("Graph Vertex Count : {0}", g.VertexCount);
     29       Console.WriteLine("Graph Edge Count : {0}", g.EdgeCount);
     30       Console.WriteLine();
     31 
     32       Console.WriteLine("Is there cycle in graph: {0}", g.HasCycle());
     33       Console.WriteLine();
     34 
     35       Edge[] mst = g.Kruskal();
     36       Console.WriteLine("MST Edges:");
     37       foreach (var edge in mst)
     38       {
     39         Console.WriteLine("t{0}", edge);
     40       }
     41 
     42       Console.ReadKey();
     43     }
     44 
     45     class Edge
     46     {
     47       public Edge(int begin, int end, int weight)
     48       {
     49         this.Begin = begin;
     50         this.End = end;
     51         this.Weight = weight;
     52       }
     53 
     54       public int Begin { get; private set; }
     55       public int End { get; private set; }
     56       public int Weight { get; private set; }
     57 
     58       public override string ToString()
     59       {
     60         return string.Format(
     61           "Begin[{0}], End[{1}], Weight[{2}]",
     62           Begin, End, Weight);
     63       }
     64     }
     65 
     66     class Subset
     67     {
     68       public int Parent { get; set; }
     69       public int Rank { get; set; }
     70     }
     71 
     72     class Graph
     73     {
     74       private Dictionary<int, List<Edge>> _adjacentEdges
     75         = new Dictionary<int, List<Edge>>();
     76 
     77       public Graph(int vertexCount)
     78       {
     79         this.VertexCount = vertexCount;
     80       }
     81 
     82       public int VertexCount { get; private set; }
     83 
     84       public IEnumerable<int> Vertices { get { return _adjacentEdges.Keys; } }
     85 
     86       public IEnumerable<Edge> Edges
     87       {
     88         get { return _adjacentEdges.Values.SelectMany(e => e); }
     89       }
     90 
     91       public int EdgeCount { get { return this.Edges.Count(); } }
     92 
     93       public void AddEdge(int begin, int end, int weight)
     94       {
     95         if (!_adjacentEdges.ContainsKey(begin))
     96         {
     97           var edges = new List<Edge>();
     98           _adjacentEdges.Add(begin, edges);
     99         }
    100 
    101         _adjacentEdges[begin].Add(new Edge(begin, end, weight));
    102       }
    103 
    104       private int Find(Subset[] subsets, int i)
    105       {
    106         // find root and make root as parent of i (path compression)
    107         if (subsets[i].Parent != i)
    108           subsets[i].Parent = Find(subsets, subsets[i].Parent);
    109 
    110         return subsets[i].Parent;
    111       }
    112 
    113       private void Union(Subset[] subsets, int x, int y)
    114       {
    115         int xroot = Find(subsets, x);
    116         int yroot = Find(subsets, y);
    117 
    118         // Attach smaller rank tree under root of high rank tree
    119         // (Union by Rank)
    120         if (subsets[xroot].Rank < subsets[yroot].Rank)
    121           subsets[xroot].Parent = yroot;
    122         else if (subsets[xroot].Rank > subsets[yroot].Rank)
    123           subsets[yroot].Parent = xroot;
    124 
    125         // If ranks are same, then make one as root and increment
    126         // its rank by one
    127         else
    128         {
    129           subsets[yroot].Parent = xroot;
    130           subsets[xroot].Rank++;
    131         }
    132       }
    133 
    134       public bool HasCycle()
    135       {
    136         Subset[] subsets = new Subset[VertexCount];
    137         for (int i = 0; i < subsets.Length; i++)
    138         {
    139           subsets[i] = new Subset();
    140           subsets[i].Parent = i;
    141           subsets[i].Rank = 0;
    142         }
    143 
    144         // Iterate through all edges of graph, find subset of both
    145         // vertices of every edge, if both subsets are same, 
    146         // then there is cycle in graph.
    147         foreach (var edge in this.Edges)
    148         {
    149           int x = Find(subsets, edge.Begin);
    150           int y = Find(subsets, edge.End);
    151 
    152           if (x == y)
    153           {
    154             return true;
    155           }
    156 
    157           Union(subsets, x, y);
    158         }
    159 
    160         return false;
    161       }
    162 
    163       public Edge[] Kruskal()
    164       {
    165         // This will store the resultant MST
    166         Edge[] mst = new Edge[VertexCount - 1];
    167 
    168         // Step 1: Sort all the edges in non-decreasing order of their weight
    169         // If we are not allowed to change the given graph, we can create a copy of
    170         // array of edges
    171         var sortedEdges = this.Edges.OrderBy(t => t.Weight);
    172         var enumerator = sortedEdges.GetEnumerator();
    173 
    174         // Allocate memory for creating V ssubsets
    175         // Create V subsets with single elements
    176         Subset[] subsets = new Subset[VertexCount];
    177         for (int i = 0; i < subsets.Length; i++)
    178         {
    179           subsets[i] = new Subset();
    180           subsets[i].Parent = i;
    181           subsets[i].Rank = 0;
    182         }
    183 
    184         // Number of edges to be taken is equal to V-1
    185         int e = 0;
    186         while (e < VertexCount - 1)
    187         {
    188           // Step 2: Pick the smallest edge. And increment the index
    189           // for next iteration
    190           Edge nextEdge;
    191           if (enumerator.MoveNext())
    192           {
    193             nextEdge = enumerator.Current;
    194 
    195             int x = Find(subsets, nextEdge.Begin);
    196             int y = Find(subsets, nextEdge.End);
    197 
    198             // If including this edge does't cause cycle, include it
    199             // in result and increment the index of result for next edge
    200             if (x != y)
    201             {
    202               mst[e++] = nextEdge;
    203               Union(subsets, x, y);
    204             }
    205             else
    206             {
    207               // Else discard the nextEdge
    208             }
    209           }
    210         }
    211 
    212         return mst;
    213       }
    214     }
    215   }
    216 }

    输出结果如下:

    参考资料

    Connectivity in a directed graph Strongly Connected Components Tarjan’s Algorithm to find Strongly Connected Components
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。