一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树(不存在回路)的n-1条边。将生成树的各边的权值相加,就是代价,我们将连通网的最小代价生成树称为最小生成树。
查找无向连通网的最小生成树,有两种经典算法—普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法,本文介绍普里姆算法。
理解本文需要先了解图的一些构造方法,参考【数据结构】图的创建与遍历
一、定义
普利姆算法定义如下:
假设 N = ( V , E ) N = (V, {E}) N=(V,E)是连通网, T E TE TE是 N N N上最小生成树中边的集合。算法从 U = { u 0 } ( u 0 ∈ V ) , T E = { } U = \{u_0\} \quad (u_0 \in V), \quad TE = \{\} U={ u0}(u0∈V),TE={ }开始。重复执行以下操作:在所有 u ∈ U , v ∈ V − U u \in U, \ v \in V-U u∈U, v∈V−U的边 ( u , v ) ∈ E (u,v) \in E (u,v)∈E中找到一条代价最小的边 ( u 0 , v 0 ) (u_0, v_0) (u0,v0)并入集合 T E TE TE,同时 v 0 v_0 v0并入 U U U,直至 U = V U = V U=V为止。此时 T E TE TE中必有 n − 1 n - 1 n−1条边,则 T = ( V , T E ) T = (V, {TE}) T=(V,TE)为 N N N的最小生成树。
二、实现思路
下图是一个连通网,我们以此来介绍普利姆算法的实现过程。
![](https://img-blog.csdnimg.cn/943f82132f1546f18ed9a10553420143.png)
此连通网 N = ( V , E ) N = (V,E) N=(V,E),V是所有顶点的集合,E是所有边的集合。
U = { v 0 } ( v 0 ∈ V ) U = \{v_0\} \quad (v_0 \in V) U={ v0}(v0∈V), U U U是生成树的点集合,以 v 0 v_0 v0为起点,开始寻找最短路径。
T E = { } TE = \{\} TE={ }是生成树的边集合,初始为空。
每次寻找离生成树最近的顶点,将其纳入生成树中,直至包含所有顶点:
(1)
U = { v 0 , v 1 } U = \{v_0, v_1\} U={ v0,v1}, T E = { ( v 0 , v 1 ) } TE = \{(v_0,v_1)\} TE={ (v0,v1)}。
(2)
U = { v 0 , v 1 , v 2 } U = \{v_0, v_1, v_2\} U={ v