图的最小生成树算法(Prim和Kruskal)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的最小生成树算法(Prim和Kruskal)相关的知识,希望对你有一定的参考价值。

参考技术A

图的邻接矩阵表示法可参考: https://www.jianshu.com/p/9f27288f6749
测试图如图所示:

思想:先选取一个顶点加入最小生成树,再选取与该顶点相连的边中的最小权值对应的顶点加入生成树,将这两个顶点作为一棵新的最小生成树,继续判断与该树相连的边的最小权值对应的顶点,并将其加入最小生成树,直到所有顶点均加入生成树为止。

测试程序

测试结果:

思想:将图的存储结构使用边集数组的形式表示,并将边集数组按权值从小到大排序,遍历边集数组,每次选取一条边并判断是否构成环路,不会构成环路则将其加入最小生成树,最终只会包含n-1条边(n为无向图的顶点数)。

边集数组的结构如图所示:

测试程序:

测试结果:

最小生成树为:

普里姆算法针对顶点展开,通过不断寻找与已构建的生成树的最小边来不断构建新的生成树。普里姆算法对于稠密图,也就是边数非常多的情况会更好一些,因为其是通过顶点来展开的。算法时间损耗主要来源于嵌套的for循环,所以时间复杂度为O(n^2)。

克鲁斯卡尔算法针对边展开,通过对边集数组的遍历来构建最小生成树,但是过程中必须避免构成环路。克鲁斯卡尔算法对于稀疏图,也就是边数较少的情况效率会很高。此算法的Find函数由边数e决定,时间复杂度为O(loge),再加上外层for循环的e次,所以时间复杂度为O(eloge)。

图论最小生成树Prim和Kruskal算法

在数据结构的教材上,讲到的图的最小生成树算法有两种,一种是Prim(普利姆)算法,一种是Kruskal(克鲁斯卡尔)算法。

两种算法的生成思路有所不同:

Prim算法:

算法思想:

  算法思想就是每次找到一个距离生成集合最近的点,加入,然后更新距离剩余点之间的距离,继续迭代。

算法步骤:

1.任意选择一个点作为起点,将该点标记为已加入最小生成树,使用一个数组表示该点已加入,join[i] = 1表示i点已加入集合;

2.将最小生成树集合作为整体,计算到其他未加入该集合的点(jion[i] == 0的点)之间的距离,使用dis[i]表示,dis[i] 表示集合距离点i之间的距离;

3.然后找出dis[i] 中距离最小的,那么 i 就是下一个要加入集合的点

4. 将join[i]赋值为1,表示已加入

5. 重新计算dis[i]。因为有新的点加入,判断该点的加入是否使集合距离其他未加入的点之间的距离变小,如果有变小,则更新dis[i]。

6.继续执行步骤3,直到所有的点都加入join数组(其实是查找n-1次后自动结束,因为指定的起始点,所有只需要再查找n-1次,即for循环从2到n即可)

疑问:Prim算法求得了最小代价,可没有保留下生产路径,不知道是不是自己的理解还不到位或者代码实现不合理。

Kruskal算法:

算法思想:

  首先将所有的边按照权重从小到大排序,然后依次取出一条边,尝试将组成集合。如果两个点已经在同一个集合,说明已经添加了,则跳过;如果尚未加入集合,这组成一个新的集合;如果是在不同的集合,则将集合合并,形成一个新的集合,直到取出n-1条有效的边或者所有点都在一个集合中,则表示已生成。

1.使用排序算法将边按权重从小到大排序

2.初始时,点均为构成集合(或者说自成集合,这里理解为未成集合),使用join数组表示集合,初始是join[i]均为0.

3.取出一条边,判断两个点 i,j

  1)如果group[i],group[j] 都为0,则说明都还没有加入集合,那么设置group[i] = group[j] = count (count用来表示加入的边数,也能够用来区分集合)

  2)如果group[i],group[j] 不相等,说明两个点不在同一个集合。

    如果i,j有一个的join值为0,说明未加入,那么只需设置这个点的join值也已加入的那个点一致。

    如果两个点都已加入集合,但是处在不同结合,那么此时就需要合并集合。(变量group,把两个集合的点设置为同样的值)

4.所有点在group里对应的值一致,表示形式了最小生成树集合。

以上是关于图的最小生成树算法(Prim和Kruskal)的主要内容,如果未能解决你的问题,请参考以下文章

[图] 最小生成树-Prime算法和Kruskal算法

急求KRUSKAL算法求最小生成树过程演示

Prim算法和Kruskal算法求最小生成树

图解:如何实现最小生成树(Prim算法与Kruskal算法)

最小生成树之Kruskal算法和Prim算法

[从今天开始修炼数据结构]图的最小生成树 —— 最清楚易懂的Prim算法和kruskal算法讲解和实现