第23章 最小生成树
23.1 最小生成树的形成
本章所讨论的两种算法都使用贪心策略,但两者使用的贪心策略有所不同。这个贪心策略可以由下面的通用方法来表达,该通用方法在每个时刻生长最小生成树的一条边,并在整个策略的实施过程中,管理一个遵守下述循环不变式的边集合A:在每遍循环之前,A是某棵最小生成树的一个子集。
23.2 Kruskal算法和Prim算法
1、Kruskal算法
- FIND-SET(u)是否等于FIND-SET(v)来判断结点u和结点v是否属于同一棵树
- 使用UNION过程来对两棵树进行合并。
- 时间复杂度为 O(ElgV)
MST-KRUSKAL(G,w){
A = new Set()
for v in G.V
MAKE-SET(v)
sort the edges of G.E into nondecreasing order by weight w
for edge(u,v) in G.E, take in nondecreasing order by weight
if FIND-SET(u) != FIND-SET(v)
A = A + {(u,v)}
UNION(u,v)
}
2、 Prim算法
- 所有不在树A中的结点都存放在一个基于key属性的最小优先队列Q中。
- 对于每个结点v,属性v.key保存的是连接v和树中结点的所有边中最小边的权重。我们约定,若不存在这样的边,则v.key = inf。
- 属性v.p给出的是结点v在树中的父结点
- 时间复杂度为 O(ElgV)
MST-PRIM(G,w,r){ //随机选择的一个开始结点r
for u in G.V
u.key = inf
u.p = NIL
r.key = 0
Q = G.V
while(!Q.isEmpty){
u = EXRACT-MIN(Q)
for v in G.Adj[u]
if v in G && w(u,v)<v.key
v.p = u
v.key = w(u,v)
}
}