最小生成树-MST算法详解及代码实现

转载 2015年11月19日 16:36:23

from http://blog.csdn.net/coder_oyang/article/details/48195405

师兄发了一篇CCF-C类的文章,但是那个会议在澳洲排名属于B类,他说他在CVPR的某一篇文章的基础之上用了MST算法,避免了局部最优解,找到了全局最优解,实验结果比原文好很多,整个文章加实验前后仅仅做了2周。真是羡煞旁人也。。其实在机器学习当中,经常会遇到局部最优解的问题,所以,就花了点时间看看MST,兴许我也能找点灵感呢,呵呵..

看完最小生成树之后得到的一个想法就是:其实MST就是一种贪心算法,每一步选择都是选取当前候选中最优的一个选择。下面详细谈谈我认识的最小生成树吧

1. 最小生成树解决什么样的问题

城市之间建设道路的问题,首先,因为道路照价较高所以我们希望总的道路是最短的;其次,我们希望造的路在每个城市之间不会形成环路。那么MST的数学表达式就是这样,期望在图 G(V,E) 中找到一个子集 T 使得,使得造价函数w(T) 最小

2. MST 伪代码

在算法导论中对最小生成树的伪代码是这样描述的:

GENERIC(G,w){
A = empty
while A does not form a spanning tree
        find an edge (u,v) that is safe for A
        A = A & (u,v)
return A
}

算法的核心是在找到一条对于集合A安全的边。那么如何定义“安全”呢?

  • 安全边

先要定义一个名词:切割:无向图 G=(V,E) (V代表图中的结点,E代表图中两个节点之间的边) 的一个切割就是 (S , V-S) 就是集合V 的一个切割。

如上图就是图 G 的一个切割实例,如果图中的某一条边 (u,v) 的一个端点位于集合 S 中,另一个端点位于 V-S 中,那么这条边横跨切割 (S , V-S)。如果集合 A 中不存在这样的横跨边,那么该切割尊重集合 A 。在横跨一个切割的所有边中,权重最小的边称为轻量级边。上图中红色结点属于集合 S ,白色结点属于集合 V-S ,横跨改切割的边是那些连接红色与白色结点的边,边 (c,d) 是横跨改切割的唯一一条轻量级边。其中红色边属于子集 A :注意切割 (S , V-S) 尊重集合A,因为集合 A 中没有横跨改切割的边。那么安全边的定于有如下定义
设G=(V , E) 是一个在边E上定义了实数权值函数 w 的的连通无向图。设集合 A 为 E 的一个子集,且 A 包括在图G的某棵最小生成树中,设 (S , V-S) 是图G中尊重集合A的任意一个切割,又设 (u,v) 是横跨切割 (S,V-S) 的一条轻量级边。那么边 (u,v) 对于集合 A 是安全的。

3. MST实现算法:Kruskal \ Prim

前文分析了MST算法核心:如何寻找安全边。这里有两种经典算法,一是Kruskal 算法,另一个是Prim算法,先来看看Kruskal 算法是如何找安全边的。

3.1 Kruskal 算法

Kruskal 算法找到安全边的想法在所有连接森林中两棵不同树的边里面,找到权重最小的边 (u,v) 。假设C1和C2为边 (u,v) 所连接的两棵树。由于边 (u,v) 一定是连接C1和其他某棵树的一条轻量级边,那么 (u,v) 一定是条安全边。

MST-KRUSKAL(G,w){
    A= NULL
    for each vector v in G.V
         MAKE-SET(v)
    sort the edges of G.E into nondecreasing order by weight w
    for each edge(u,v) in G.E, taken in nondecreasing order by weight
         if FIND-SET(v) != FIND-SET(u)
            A = A & {(u,v)}
            UNION(u,v)
    return A
}

说明:FIND-SET(v) != FIND-SET(u) 判断结点 u , v 是否属于同一棵树,下面是执行Kruskal算法的过程,红色的边属于不断增长的森林A。该算法按照边的权值大小一次进行考虑,箭头所指的边是算法每一步所考察的边。如果该条边将两棵不同的树连接起来,它就被加入到森林里面去,从而完成对两棵树的合并。

总结Kruskal 算法:1: 连接的是两颗不同的树   2:选取的是轻量级边   循着这两个条件便实现Kruskal 算法

算法代码见 算法导论 19-2 采用二项堆的最小生成树算法

3.2 Prim 算法

Prim算法所具有的一个性质是集合 A 中的边总是构成一棵树。从任意的根结点出发,一直长大到覆盖 V 中的所有结点为止。算法每一步在连接集合A与A之外的结点的所有边中,选择一条轻量级边加入到 A 中,下面是执行Prim算法的过程

其中红色边与结点都属于树A。在每一步算法中,树的结点就决定了图的一个切割,横跨该切割的一条轻量级边被加入到树中。


参考文献

算法导论 Thomas H. et.al


最小生成树-MST算法详解及代码实现

最小生成树,贪心算法,Kruskal,Prim算法

最小生成树的Kruskal算法java代码实现

import java.util.List; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; i...

java实现图的最小生成树(MST)的普利姆(Prim)算法

/****************************************************************************** * Compilation: ja...

java实现图的最小生成树(森林)MST克鲁斯卡尔(Kruskal)算法

/****************************************************************************** * Compilation: ja...

Prim算法实现最小生成树MST

//实现文件 #include #include #include #include #include using namespace std; //用STL中的优先队列实现 name...

图 之 MST(最小生成树 — kruskal算法 )并查集实现

#并查集的优化: (1)       Find_Set(x)时,路径压缩寻找祖先时,我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度。为...

Prim算法实现最小生成树MST(java)

Prim算法是另一种生成图的最小生成树的算法,这里简单说一下Prim算法和Kruskal算法的在实现方面的区别:1、Kruskal算法在生成最小生成树的过程中产生的是森林,Prim算法在执行过程中始终...

最小生成树MST -- Prim 算法实现

最小生成树MST最小生成树定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。Prim algorithm: Prim算法简述...
  • lllllyt
  • lllllyt
  • 2017年05月20日 20:28
  • 72

Graph的算法实现: 寻找一幅图的最小生成树(MST)

一个graph 只有一个最小生成树(minimum spanning tree). 寻找最小生成树有
  • a130737
  • a130737
  • 2014年07月06日 15:53
  • 445

最小生成树的Prim算法和Kruskal算法java代码实现

最小生成树的Prim算法和Kruskal算法java代码实现
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:最小生成树-MST算法详解及代码实现
举报原因:
原因补充:

(最多只允许输入30个字)