Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)

最小生成树

图算法(连通无向图)中有一类经典问题,叫做最小生成树(Minimal Spanning Tree)。简单
的来说,最小生成树问题是这样一种问题 : 在连接所有图顶点的情况下,求使得所选边的权重和最
小的方案。

算法导论中主要介绍了两种经典的算法:

  1. Kruskal算法
  2. Prim算法

两种算法都采用贪心算法来解决问题。书中描述最小生成树的通用贪心解决方案

遵循一个循环不变式的边集合A:

在每遍循环之前,A是某棵最小生成树的一个子集。

这种策略一般并不能保证找到一个全局最优的解决方案。但对于最小生成树问题来说,
我们可以证明,某些贪心策略确实能够找到一棵权重最小的生成树。

Kruskal算法中,集合A是一个森林 ,其节点就是给定图的节点。每次加入到集合A中的安全边永
远是权重最小的连接两个不同分量的边。在Prim中,集合A则是一棵。每次加入到A中的安全
边永远是连接A和A之外某个节点的边中权重最小的。

Kruskal算法

核心

将图节点看成森林,不断选择连接任意两森林的权重最小的边、合并森林,通过不断重复选择、合并
,最后将所有森林合并成一棵树。

初始

每个图节点即为一个森林:

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第1张图片

选择

选择连接任意两个森林的权重最小的边,这里是h->g:

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第2张图片

合并

合并选中的边的两个节点所在的两个森林:

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第3张图片

重复

不断重复选择、合并操作,直到所有节点合并成一颗树。

结果

被深灰色涂中的边即为选中边:

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第4张图片

Code

https://code.csdn.net/snippets/1346944
(注:编译、运行通过。运行环境:windows8.1 VS2013)

读者可自行下载代码,编译运行并与上图对照。

Prim 算法

核心

将图节点看成一棵树和剩余节点,选择一个根节点,选择与树相邻的最小边、将节点合并到树中,通
过不断重复选择、合并,最终将所有节点合并到树中。

根节点

随机选择一个根节点(图中涂黑的即为选择的根节点:a):

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第5张图片

初始

一棵只包含根节点a的树、剩余节点(除根节点a外所有节点,即蓝色实线框出的节点):

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第6张图片

选择

选择一条与树相连的权重最小的边:

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第7张图片

合并

将所选边所连接的两端合并(即将节点合并到树中):

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第8张图片

重复

重复选择、合并过程,直到所有节点都被包含在树中。

结果

被深灰色涂中的边即为选中边:

Introduce to algorithm--------pseudo code to C/C++ code (chapter 23)_第9张图片

Code

https://code.csdn.net/snippets/1347811
(注:编译、运行通过。运行环境:windows8.1 VS2013)

More

值得一提的是,上图所示的最小生成树不是唯一的。边 b->c 与 a->h 权重相同,也就是说,将
前一条边替换为后一条边所构造出来的MST同为最优解。

你可能感兴趣的:(Introduce,to,algorithm)