📅  最后修改于: 2023-12-03 15:41:03.990000             🧑  作者: Mango
在计算机科学中,生成树是一种树形数据结构,由图中的所有节点组成,形成一棵无环子图。生成树在离散数学中有广泛的应用,其中包括连通性、网络流、最短路径等领域。
最小生成树是一种生成树,其边的权值之和最小。最小生成树算法包括普林姆算法和克鲁斯卡尔算法。
普林姆算法使用一个辅助数组 key[]
来保存每个节点与当前生成树的边中最小权值。初始化数组 key[]
的值为无穷大。将第一个节点加入生成树,然后根据 key[]
来选择下一个节点加入生成树。依次类推,直到生成整个树。
普林姆算法的时间复杂度为 O(V²),其中 V 是节点数量。
以下是普林姆算法的 Python 代码实现:
def prim(graph):
n = len(graph)
visited = [False] * n
key = [float('inf')] * n
parent = [-1] * n
key[0] = 0
for _ in range(n):
u = key.index(min(key))
visited[u] = True
for v in range(n):
if graph[u][v] and not visited[v] and graph[u][v] < key[v]:
key[v] = graph[u][v]
parent[v] = u
return parent
克鲁斯卡尔算法是一种基于贪心思想的最小生成树算法。它的基本思路是将所有边按权值从小到大排序,然后依次选取边加入生成树,保证不形成环。直到生成整个树。
克鲁斯卡尔算法的时间复杂度为 O(E log E),其中 E 是边数量。
以下是克鲁斯卡尔算法的 Python 代码实现:
class Subset:
def __init__(self, parent, rank):
self.parent = parent
self.rank = rank
def find(subsets, i):
if subsets[i].parent != i:
subsets[i].parent = find(subsets, subsets[i].parent)
return subsets[i].parent
def union(subsets, x, y):
x_root = find(subsets, x)
y_root = find(subsets, y)
if subsets[x_root].rank < subsets[y_root].rank:
subsets[x_root].parent = y_root
elif subsets[x_root].rank > subsets[y_root].rank:
subsets[y_root].parent = x_root
else:
subsets[y_root].parent = x_root
subsets[x_root].rank += 1
def kruskal(graph):
result = []
i, e = 0, 0
n = len(graph)
graph_sorted = sorted([(graph[i][j], i, j) for i in range(n) for j in range(i+1, n) if graph[i][j]], key=lambda x: x[0])
subsets = [Subset(i, 0) for i in range(n)]
while e < n - 1:
w, u, v = graph_sorted[i]
i += 1
x = find(subsets, u)
y = find(subsets, v)
if x != y:
e += 1
result.append((u, v))
union(subsets, x, y)
return result