目录
最小生成树算法复习
求最小生成树是数据结构中图的一种重要应用,一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。
而求最小生成树有两种算法,一种是Prim算法,一种是Kruskal算法。
1.Prim算法
Prim 算法求最小生成树,它的要求是从一个带权无向完全图中选择 n-1 条边并使这个图仍然连通 (也即得到了一棵生成树 ),同时还要考虑使树的权最小。
Prim算法的适用范围:MST(Minimum Spanning Tree,最小生成树), 无向图(有向图的是最小树形图), 多用于稠密图(点少边多) 。
算法描述
(1)输入:一个加权连通图,其中顶点集合为V,边集合为E;
(2)初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
(3)在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
(4)将v加入集合Vnew中,将<u, v>边加入集合Enew中;
(5)如果Vnew = V,结束,否则回到(3)。
用通俗话说一遍就是,从边集合里依次选权值最小、一个端点在新点集中一个端点在剩下的原集合中、的边加入新的边集,直到所有点都在新的点集中。新点集合新边集即为输出的最小生成树。
根据算法描述,一个常规的思路是每次都对顶点集Vnew中点的所有对应边进行排序,然后选取权值最小的边,这样很容易得到算法复杂度为O(E^2),我们可以维护一个小根堆,新点集中每加入一个新点,就将新点对应的边权值放入边中,这样时间复杂度就可以降到O(ElogE)。
2.Kruskal 算法
Kruskal算法每次选择 n- 1 条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。注意到所选取的边若产生环路则不可能形成一棵生成树。Kruskal算法分 e 步,其中 e 是网络中边的数目。按耗费递增的顺序来考虑这 e 条边,每次考虑一条边。当考虑某条边时,若将其加入到已选边的集合中会出现环路,则将其抛弃,否则,将它选入。
适用范围:MST(Minimum Spanning Tree,最小生成树), 无向图(有向图的是最小树形图), 多用于稀疏图(点多边少) ,边已经按权值排好序给出。
算法描述
(1)记Graph中有v个顶点,e条边;
(2)新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边;
(3)将原图Graph中所有e个边按权值从小到大排序;
(4)循环:从权值最小的边开始遍历每条边,如果这条边连接的两个节点于图Graphnew中不在同一个连通分量中(不连通), 添加这条边到图Graphnew中,直至图Graph中所有的节点都在同一个连通分量中(都连通)。
检查 2 个顶点是否在同一连通分量可以使用并查集实现(连通分量看作等价类),并查集相关内容可以查看我的上一篇博文,算法的主要时间复杂度在于将边排序上。