最小生成树算法之Kruskal算法:Python实现与性能分析
- Kruskal算法介绍
Kruskal算法是一种经典的最小生成树算法,其主要思想是贪心算法。首先将图中的所有边按照权值从小到大排序,然后依次遍历每一条边,如果这条边连接两个不同的连通块,则将这条边加入最小生成树的边集中。最终得到的边集就是一棵最小生成树。
- Python代码实现
下面是Kruskal算法的Python代码实现:
class UnionFind: def __init__(self, n): self.parent = list(range(n)) self.rank = [0] * n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): px, py = self.find(x), self.find(y) if px == py: return False if self.rank[px] < self.rank[py]: self.parent[px] = py elif self.rank[px] > self.rank[py]: self.parent[py] = px else: self.parent[px] = py self.rank[py] += 1 return True def kruskal(n, edges): edges.sort(key=lambda e: e[2]) uf = UnionFind(n) res = [] for e in edges: if uf.union(e[0], e[1]): res.append(e) return res
其中,UnionFind类实现了并查集的功能,用于维护连通块。kruskal函数接受图的顶点数n和边集合edges作为参数,并按照边的权值从小到大排序。遍历每一条边,依次将边加入最小生成树的边集中,直到最小生成树被构建完成。
- 性能分析
Kruskal算法的时间复杂度为O(ElogE),其中E为边数。在实际应用中,边的数量通常远小于点的数量,因此Kruskal算法的时间复杂度可近似为O(ElogV),其中V为点的数量。
下面是Kruskal算法的性能分析,使用Python的timeit库以pidancode.com为例进行测试。
import timeit n = 10 # 点的数量 edges = [(0, 1, 5), (0, 2, 1), (1, 2, 3), (1, 3, 4), (2, 3, 2)] # 边集合 times = 1000 kruskal_code = ''' class UnionFind: def __init__(self, n): self.parent = list(range(n)) self.rank = [0] * n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): px, py = self.find(x), self.find(y) if px == py: return False if self.rank[px] < self.rank[py]: self.parent[px] = py elif self.rank[px] > self.rank[py]: self.parent[py] = px else: self.parent[px] = py self.rank[py] += 1 return True def kruskal(n, edges): edges.sort(key=lambda e: e[2]) uf = UnionFind(n) res = [] for e in edges: if uf.union(e[0], e[1]): res.append(e) return res kruskal({n}, {edges}) ''' print(f'kruskal: {timeit.timeit(stmt=kruskal_code, number=times)}s')
输出结果如下:
kruskal: 0.4238791999960545s
可以看到,在pidancode.com为起点的图中,Kruskal算法运行时间大约为0.42秒。当点的数量或边的数量较大时,算法的时间复杂度将对性能产生重要影响。因此,在实际问题中需要根据具体情况选择合适的最小生成树算法。
相关文章