描述:有A、B、C、D四个点,每两个点之间的距离(无方向)是(第一个数字是两点之间距离,后面两个字母代表两个点):(1,‘A‘,‘B‘),(5,‘A‘,‘C‘),(3,‘A‘,‘D‘),(4,‘B‘,‘C‘),(2,‘B‘,‘D‘),(1,‘C‘,‘D‘) 生成边长和最小的树,也就是找出一种连接方法,将各点连接起来,并且各点之间的距离和最小。
#! /usr/bin/env python #coding:utf-8 #以全局变量X定义节点集合,即类似{'A':'A','B':'B','C':'C','D':'D'}, #如果A、B两点联通,则会更改为{'A':'B','B':'B",...},即任何两点联通之后,两点的值value将相同。 X = dict() #各点的初始等级均为0,如果被做为连接的的末端,则增加1 R = dict() #设置X R的初始值 def make_set(point): X[point] = point R[point] = 0 #节点的联通分量 def find(point): if X[point] != point: X[point] = find(X[point]) return X[point] #连接两个分量(节点) def merge(point1,point2): r1 = find(point1) r2 = find(point2) if r1 != r2: if R[r1] > R[r2]: X[r2] = r1 else: X[r1] = r2 if R[r1] == R[r2]: R[r2] += 1 #KRUSKAL算法实现 def kruskal(graph): for vertice in graph['vertices']: make_set(vertice) minu_tree = set() edges = list(graph['edges']) edges.sort() #按照边长从小到达排序 for edge in edges: weight, vertice1, vertice2 = edge if find(vertice1) != find(vertice2): merge(vertice1, vertice2) minu_tree.add(edge) return minu_tree if __name__=="__main__": graph = { 'vertices': ['A', 'B', 'C', 'D', 'E', 'F'], 'edges': set([ (1, 'A', 'B'), (5, 'A', 'C'), (3, 'A', 'D'), (4, 'B', 'C'), (2, 'B', 'D'), (1, 'C', 'D'), ]) } result = kruskal(graph) print result
#! /usr/bin/env python #coding:utf-8 class UnionFind: def __init__(self): self.weights = {} self.parents = {} def __getitem__(self, object): if object not in self.parents: self.parents[object] = object self.weights[object] = 1 return object path = [object] root = self.parents[object] while root != path[-1]: path.append(root) root = self.parents[root] for ancestor in path: self.parents[ancestor] = root return root def __iter__(self): return iter(self.parents) def union(self, *objects): roots = [self[x] for x in objects] heaviest = max([(self.weights[r],r) for r in roots])[1] for r in roots: if r != heaviest: self.weights[heaviest] += self.weights[r] self.parents[r] = heaviest #判断是否是无向图 def isUndirected(G): for v in G: if v in G[v]: return False for w in G[v]: if v not in G[w]: return False return True #最小生成树 import unittest def MinimumSpanningTree(G): if not isUndirected(G): raise ValueError("MinimumSpanningTree: input is not undirected") for u in G: for v in G[u]: if G[u][v] != G[v][u]: raise ValueError("MinimumSpanningTree: asymmetric weights") subtrees = UnionFind() tree = [] for W,u,v in sorted((G[u][v],u,v) for u in G for v in G[u]): if subtrees[u] != subtrees[v]: tree.append((u,v)) subtrees.union(u,v) return tree #单元测试 class MSTTest(unittest.TestCase): def testMST(self): G = {0:{1:11,2:13,3:12},1:{0:11,3:14},2:{0:13,3:10},3:{0:12,1:14,2:10}} T = [(2,3),(0,1),(0,3)] for e,f in zip(MinimumSpanningTree(G),T): self.assertEqual(min(e),min(f)) self.assertEqual(max(e),max(f)) if __name__ == "__main__": unittest.main()
参考资料
1.《算法基础》(GILLES Brassard,Paul Bratley)
2.http://www.ics.uci.edu/~eppstein/PADS/
更多相关代码,请访问:https://github.com/qiwsir/algorithm
无向图最小生成树Kruskal算法,布布扣,bubuko.com
原文:http://blog.csdn.net/qiwsir/article/details/32102089