个人主页:丷从心
系列专栏:贪心算法
Kruskal
算法Kruskal
算法所需的时间是 O ( e log e ) O(e \log{e}) O(eloge)Kruskal
算法比Prim
算法差,当 e = o ( n 2 ) e = o(n^{2}) e=o(n2)时,Kruskal
算法比Prim
算法好得多Python
实现class Graph:
def __init__(self, vertices):
self.V = vertices # 图中顶点的数量
self.graph = [] # 存储图的边的列表
def addEdge(self, u, v, w):
self.graph.append([u, v, w]) # 添加边到图的边列表
def find(self, parent, i):
if parent[i] == i: # 如果顶点 i 的根节点是自身, 则返回 i
return i
return self.find(parent, parent[i]) # 递归查找 i 的根节点
def union(self, parent, rank, x, y):
root_x = self.find(parent, x) # 查找顶点 x 的根节点
root_y = self.find(parent, y) # 查找顶点 y 的根节点
if rank[root_x] < rank[root_y]: # 如果 x 的根节点的秩小于 y 的根节点的秩
parent[root_x] = root_y # 将 x 的根节点连接到 y 的根节点
elif rank[root_x] > rank[root_y]: # 如果 x 的根节点的秩大于 y 的根节点的秩
parent[root_y] = root_x # 将 y 的根节点连接到 x 的根节点
else: # 如果 x 和 y 的根节点的秩相同
parent[root_y] = root_x # 将 y 的根节点连接到 x 的根节点
rank[root_x] += 1 # 增加 x 的根节点的秩
def kruskalMST(self):
result = [] # 存储最小生成树的边的列表
i = 0 # 当前处理的边的索引
e = 0 # 已经加入最小生成树的边的数量
self.graph = sorted(self.graph, key=lambda x: x[2]) # 按照边的权重对图的边进行排序
parent = [] # 存储顶点的父节点
rank = [] # 存储顶点的秩
for node in range(self.V):
parent.append(node) # 每个顶点的初始父节点是自身
rank.append(0) # 每个顶点的初始秩是 0
while e < self.V - 1: # 当最小生成树的边的数量小于 V - 1 时, 继续循环
u, v, w = self.graph[i] # 获取当前处理的边的源顶点、目标顶点和权重
i += 1 # 增加边的索引
x = self.find(parent, u) # 查找 u 的根节点
y = self.find(parent, v) # 查找 v 的根节点
if x != y: # 如果 u 和 v 不在同一个连通分量中(不会形成环路)
e += 1 # 增加已加入最小生成树的边的数量
result.append([u, v, w]) # 将该边加入最小生成树的结果中
self.union(parent, rank, x, y) # 合并 u 和 v 所在的连通分量
print('边\t\t权')
for u, v, weight in result:
print(f'{u} - {v}\t{weight}') # 打印最小生成树的边和权重
g = Graph(5)
g.addEdge(0, 1, 2)
g.addEdge(0, 3, 6)
g.addEdge(1, 3, 8)
g.addEdge(1, 2, 3)
g.addEdge(1, 4, 5)
g.addEdge(2, 4, 7)
g.addEdge(3, 4, 9)
g.kruskalMST()
边 权
0 - 1 2
1 - 2 3
1 - 4 5
0 - 3 6