算法:最小生成树(Minimum Spanning Tree)
生成树指的是一个连通图G的覆盖所有顶点的无环子图,最小生成树指的是所有生成树中加权和最小的生成树。
最小生成树的应用:聚类分析、网络架构设计、VLSI布线设计等诸多实际应用问题,都可转化并描述为最小支 撑树的构造问题。在这些应用中,边的权重大多对应于某种可量化的成本,因此作为对应优化问 题的基本模型,最小支撑树的价值不言而喻。——《数据结构C++版》
求最小支撑树的算法主要采用贪心算法,最著名的两个算法分别是Prim算法和Kruskal算法。
本篇主要参考Kruskal’s Minimum Spanning Tree Algorithm | Greedy Algo-2 - GeeksforGeeks以及以及Prim’s Minimum Spanning Tree (MST) | Greedy Algo-5 - GeeksforGeeks,GeeksforGeeks上的数据结构今天刚好搜到了,确实讲的不错,转载收藏一下作为笔记。
Prim算法
使用Prim算法之前,需要了解图论中的一个概念。割(Cut or Cross edges )指的是连接两个子图的边。Prim算法从图中的任意一个点出发,选出所有割中的最小边加入到MST中,直到所有的顶点都在MST中。算法的思想很简单,代码如下
1 | // A C++ program for Prim's Minimum |
这里的代码主要使用的是图的邻接矩阵表示,采用的思想是维护一个与剩余的子图相连的割的数组,在添加边的时候更新这个数组,每次添加的时候就可以从这个数组中寻找最小的割,时间复杂度为O(V^2),还有另外一种邻接表的表示方法,使用邻接表和优先队列可以将时间复杂度降为O(E log V),更加复杂一些,参考Prim’s MST for Adjacency List Representation | Greedy Algo-6 - GeeksforGeeks。
Kruskal算法
首先,将G中的所有边E按照权重从小到大进行排序,然后依次遍历,如果将当前的边加入当前的子图中不会产生环,那么就加入当前的边,否则继续遍历下一个最小边,直到所有的边都被遍历。这里产生的一个问题就是如何判断是否是有环图,这里我们可以是用压缩路径的并查集算法,参考Union-Find Algorithm | Set 2 (Union By Rank and Path Compression) - GeeksforGeeks,代码如下。
1 |
|
参考资料
- 《数据结构C++版-邓俊辉》6.11 最小支撑树
- Kruskal’s Minimum Spanning Tree Algorithm | Greedy Algo-2 - GeeksforGeeks
- Prim’s Minimum Spanning Tree (MST) | Greedy Algo-5 - GeeksforGeeks
- Union-Find Algorithm | Set 2 (Union By Rank and Path Compression) - GeeksforGeeks
- Prim’s MST for Adjacency List Representation | Greedy Algo-6 - GeeksforGeeks
- 算法学习笔记(1) : 并查集 - 知乎 (zhihu.com)