1. 最小生成树:
最小生成树即为图中权值最小的生成树(生成树中所有边权重之和)。
例如对于无向图:
来说最小生成树就是:
1.1 最小生成树算法
最小生成树的算法主要有两个:
- Kruskal 算法
- Prim 算法
1.1.1 Kruskal 算法
算法演示如下:
代码如下,嵌入到上一篇论文的图构造里面 Python 图(Graph)数据结构(一):图的构造与遍历(深度优先 DFS 和广度优先 BFS):
def cruskal(self):
edges = self.edges()
edges.sort(key=lambda edges: edges[2])
connet = {}
res = []
vertices = self.vertices()
for node in vertices:
connet[node] = node
for from_node, to_node, weight in edges:
if connet[from_node] != connet[to_node]:
res.append(([from_node, to_node], weight))
if len(res) == self.vertex_num() - 1:
break
a, b = connet[from_node], connet[to_node]
for key in connet:
if connet[key] == b:
connet[key] = a
return res
connect 字典的作用是避免环的产生,每次连接之后要合并相关点的连通分量。每次连接之前需要判断连接的边上的两个点是否在一个连通分量里面,如果是,则不连接,如果不是再连接,并修改相关连通分量。
1.1.2 Prim 算法
prim 算法的演示如下:
代码:
def prim(self):
edges = self.edges()
edges.sort(key=lambda edges: edges[2])
vertices = self.vertices()
node = vertices[0]
res = []
node_visited = set()
node_visited.add(node)
while len(res) < self.vertex_num() - 1:
for from_node, to_node, weight in edges:
if from_node in node_visited:
if to_node not in node_visited:
node_visited.add(to_node)
res.append(([from_node, to_node], weight))
break
if to_node in node_visited:
if from_node not in node_visited:
node_visited.add(from_node)
res.append(([from_node, to_node], weight))
break
return res
node_visited 字典存储已经连接过的节点,选择边时,边中必须有且只有一个节点输入 visited,并且是权值最小的才连接,并且将另一个没有连接过的点放入 node_visited 中。