Skip to content

最小生成树

最小生成树(MST)是连接图中所有节点的最小权重路径集合。

Prim 算法

概述

Prim 算法从一个起始节点开始,逐步添加权重最小的边来构建生成树。

实现

python
import heapq

def prim(graph, start):
    mst = []
    visited = {start}
    edges = [(weight, start, neighbor) for neighbor, weight in graph[start].items()]
    heapq.heapify(edges)
    
    while edges:
        weight, u, v = heapq.heappop(edges)
        
        if v not in visited:
            visited.add(v)
            mst.append((u, v, weight))
            
            for next_neighbor, next_weight in graph[v].items():
                if next_neighbor not in visited:
                    heapq.heappush(edges, (next_weight, v, next_neighbor))
    
    return mst

# 示例图
graph = {
    'A': {'B': 2, 'C': 3},
    'B': {'A': 2, 'C': 1, 'D': 1},
    'C': {'A': 3, 'B': 1, 'D': 2},
    'D': {'B': 1, 'C': 2}
}

print("Prim 最小生成树:", prim(graph, 'A'))

Kruskal 算法

概述

Kruskal 算法按权重从小到大排序边,依次添加边直到形成生成树。

实现

python
def kruskal(graph):
    # 获取所有边并排序
    edges = []
    for node in graph:
        for neighbor, weight in graph[node].items():
            edges.append((weight, node, neighbor))
    
    edges.sort()
    
    # 并查集
    parent = {}
    
    def find(node):
        if parent[node] != node:
            parent[node] = find(parent[node])
        return parent[node]
    
    def union(node1, node2):
        root1 = find(node1)
        root2 = find(node2)
        if root1 != root2:
            parent[root2] = root1
    
    # 初始化父节点
    for node in graph:
        parent[node] = node
    
    mst = []
    for weight, u, v in edges:
        if find(u) != find(v):
            union(u, v)
            mst.append((u, v, weight))
    
    return mst

# 示例
print("Kruskal 最小生成树:", kruskal(graph))

复杂度分析

算法时间复杂度空间复杂度适用场景
PrimO(E + V log V)O(V)稠密图
KruskalO(E log E)O(E)稀疏图

应用场景

  • 网络布线
  • 电路设计
  • 聚类分析