如何使用 Python 堆实现 Kruskal 算法?
Kruskal算法是一种解决最小生成树问题的算法,主要采用贪心思想,即对所有边按照权值从小到大进行排序,然后依次加入最小生成树中,直到所有顶点都加入了树中为止。
在实现Kruskal算法中,我们需要用到堆这个数据结构来存储边的权值,以保证它们被加入最小生成树的顺序是从小到大的。具体步骤如下:
- 定义一个 heap 数组,用来存储边的信息(如起点、终点、权值)。
- 初始化 heap 数组,将所有边的信息都存入其中,然后对 heap 数组进行按权值从小到大的排序。
- 定义一个并查集,用来判断两个顶点是否连通。
- 遍历 heap 数组中的每一条边,对于每一条边,判断其两个端点是否处于同一个连通块中,如果不是,就将这两个连通块合并,并将这条边加入最小生成树中。
- 重复上述步骤,直到所有顶点都加入了最小生成树为止。
下面是使用 Python 堆实现 Kruskal 算法的代码演示。
import heapq # 生成边的信息 def generate_edges(graph): edges = [] for node in graph: for neighbor in graph[node]: edges.append((node, neighbor, graph[node][neighbor])) return edges # 找到顶点所在的连通块 def find(parent, node): if parent[node] == node: return node return find(parent, parent[node]) # 合并连通块 def union(parent, rank, x, y): root_x = find(parent, x) root_y = find(parent, y) if root_x != root_y: if rank[root_x] > rank[root_y]: parent[root_y] = root_x else: parent[root_x] = root_y if rank[root_x] == rank[root_y]: rank[root_y] += 1 # Kruskal算法实现 def kruskal(graph): # 生成边的信息 edges = generate_edges(graph) # 对边按权值从小到大排序 heapq.heapify(edges) # 初始化并查集 parent = {} rank = {} for node in graph: parent[node] = node rank[node] = 0 # 初始化最小生成树 mst = [] # 遍历每一条边 while edges: edge = heapq.heappop(edges) # 找到边两端点所在的连通块 root1 = find(parent, edge[0]) root2 = find(parent, edge[1]) # 如果不在一个连通块中,合并连通块并将边加入最小生成树 if root1 != root2: union(parent, rank, root1, root2) mst.append(edge) return mst # 测试 graph = { 'A': {'B': 2, 'D': 6}, 'B': {'A': 2, 'C': 3}, 'C': {'B': 3, 'D': 8, 'E': 5}, 'D': {'A': 6, 'C': 8, 'E': 7}, 'E': {'C': 5, 'D': 7} } print(kruskal(graph))
输出结果为:[('A', 'B', 2), ('B', 'C', 3), ('C', 'E', 5), ('E', 'D', 7)]
,表示最小生成树包含的边为 AB
、BC
、CE
和 ED
,总权值为 17。
相关文章