数据结构-最小生成树

155 阅读2分钟

前言

最小生成树可以用一个实际例子来说明:就像日常生活中修路一样,如果一个地区有5个建筑,它们之间还没有建造公路连通它们,建筑之间修路的成本也不一样。那么,该如何建造公路将它们连通起来,并使修路的开销最小呢?这就是最小生成树问题的具象化体现。

概念

图和树不一样,图当中存在回路,不同顶点之间相连的边的权值也不相同,在图中找到一个路径(或者说一个树),使得所有顶点连通的同时边的权值最小,那么这棵树就是这个图的最小生成树。

一棵树最小生成树可能并不唯一,但是它们的总权值都是一致的,都是生成树权值的最小值。

计算机中求得一个图的最小生成树一般有两种算法,分别是Prim算法和Kruskal算法。

Prim(普里姆)算法

原理

Prim算法基于顶点出发。设有任意图G,G中的顶点数目为nn,在图G中任选一个顶点a为起点,寻找距离该顶点最近的顶点b,并记录这些顶点和边的权值。此时已经遍历22个顶点和11条边。之后再次寻找距离顶点集合(此时顶点集合中有顶点a和顶点b)最近的顶点c,并记录下该顶点和最近边的权值,以此类推。直到所有顶点全部遍历完成。此时就能得到一棵结点数目为nn,边数目为n1n-1的路径,该路径没有回路,是图G的一棵权值最小的生成树。

性能

时间复杂度:Prim算法的空间复杂度为O(V2)O(V^2)

适用:Prim算法的实现并不依赖于图当中边的数目,即与EE无关,因此它适用于顶点少而边较多的稠密图。

Kruskal(克鲁斯卡尔)算法

原理

和Prim算法不同,Kruskal算法基于最短边出发。设有任意图G,G中的边数为EE,在G中选中一条权值最低的边a,并记录该条边连接的两个顶点。之后再在G中寻找一条权值最低的边b,但这条边的两端顶点最多只能有一个顶点被记录过,否则只能寻找除该边外权值最低的边,以此类推。直到所有顶点全部被遍历完成。此时就会得到该图G的最小生成树。

性能

时间复杂度:由于Kruskal算法采用堆结构存放边集,因此每次选择新边时只需要O(log2E)O(\log_2E)的时间,算法总的时间复杂度为O(Elog2E)O(E\log_2E)

适用:不难看出,Kruskal算法的时间复杂度只与边有关,因此它适用于顶点多但是边较少的稀疏图。