📅  最后修改于: 2023-12-03 14:56:00.314000             🧑  作者: Mango
最小生成树是指在一张加权无向图中,包含所有顶点的生成树中,边的权值之和最小的一棵生成树。Kruskal 和 Prim 算法是两种常用的求解最小生成树的算法。
本文将介绍 Kruskal 和 Prim 算法的基本思路和实现步骤,并给出 Python 代码实现。
Kruskal 算法是一种贪心算法,其基本思路是:
Kruskal 算法的实现步骤如下:
以下是 Kruskal 算法的 Python 代码实现:
def kruskal(graph):
parent = {}
rank = {}
result = []
edges = sorted(graph.edges.items(), key=lambda x: x[1]) # 按边权从小到大排序
for node in graph.nodes:
parent[node] = node
rank[node] = 0
def find(node):
if parent[node] != node:
parent[node] = find(parent[node])
return parent[node]
def union(node1, node2):
root1, root2 = find(node1), find(node2)
if root1 != root2:
if rank[root1] > rank[root2]:
parent[root2] = root1
else:
parent[root1] = root2
if rank[root1] == rank[root2]:
rank[root2] += 1
return True
else:
return False
for edge in edges:
node1, node2 = edge[0]
if union(node1, node2):
result.append((node1, node2))
if len(result) == len(graph.nodes) - 1:
break
return result
其中,graph
是一个图对象,包括两个属性:nodes
表示节点集合,edges
表示边和边权的字典,例如:
graph = {
"nodes": ["A", "B", "C", "D", "E", "F"],
"edges": {
("A", "B"): 1, ("A", "C"): 4, ("B", "C"): 2,
("B", "D"): 5, ("C", "D"): 3, ("C", "E"): 6,
("D", "E"): 7, ("D", "F"): 8, ("E", "F"): 9
}
}
Prim 算法也是一种贪心算法,其基本思路是:
Prim 算法的实现步骤如下:
以下是 Prim 算法的 Python 代码实现:
from heapq import heappush, heappop
def prim(graph):
parent = {}
key = {}
heap = []
result = []
for node in graph.nodes:
key[node] = float("inf")
start_node = graph.nodes[0]
key[start_node] = 0
heappush(heap, (key[start_node], start_node))
while heap:
weight, node = heappop(heap)
if node not in parent:
parent[node] = None
for neighbour in graph.edges[node]:
if neighbour not in parent and graph.edges[node][neighbour] < key[neighbour]:
key[neighbour] = graph.edges[node][neighbour]
heappush(heap, (key[neighbour], neighbour))
if parent[node]:
result.append((parent[node], node))
return result
其中,graph
是一个图对象,包括两个属性:nodes
表示节点集合,edges
表示边和边权的字典,例如:
graph = {
"nodes": ["A", "B", "C", "D", "E", "F"],
"edges": {
"A": {"B": 1, "C": 4},
"B": {"A": 1, "C": 2, "D": 5},
"C": {"A": 4, "B": 2, "D": 3, "E": 6},
"D": {"B": 5, "C": 3, "E": 7, "F": 8},
"E": {"C": 6, "D": 7, "F": 9},
"F": {"D": 8, "E": 9}
}
}
Kruskal 算法和 Prim 算法都是求解最小生成树的经典算法,它们的时间复杂度均为 O(ElogE),其中 E 表示边数。两个算法的主要区别在于,Kruskal 算法是基于边的操作,Prim 算法是基于节点的操作。在实际应用中,我们可以根据具体的问题选择适合的算法。