# 最小生成树算法

# 概述

最小生成树(Minimum Spanning Tree,MST)是一个带权无向图所有生成树中权值和最小的生成树。本文介绍两种经典的最小生成树算法:Prim算法和Kruskal算法。

# Prim算法

# 算法原理

Prim算法从任意顶点开始,每次选择一个与当前树距离最近的顶点加入树中,直到所有顶点都被加入为止。

# 算法步骤

  1. 选择任意顶点作为起始点,加入MST
  2. 找到与当前MST中顶点相连的最小权值边
  3. 将该边连接的未访问顶点加入MST
  4. 重复步骤2-3直到所有顶点都在MST中

# 复杂度分析

  • 时间复杂度:O(V^2),其中V是顶点数
  • 空间复杂度:O(V)

# 代码实现

def prim(graph):
    n = len(graph)
    selected = [False] * n
    selected[0] = True
    edges = 0
    mst_weight = 0
    
    while edges < n - 1:
        minimum = float('inf')
        x = 0
        y = 0
        
        for i in range(n):
            if selected[i]:
                for j in range(n):
                    if not selected[j] and graph[i][j]:
                        if graph[i][j] < minimum:
                            minimum = graph[i][j]
                            x = i
                            y = j
        
        selected[y] = True
        mst_weight += graph[x][y]
        edges += 1
    
    return mst_weight

# 示例

比较次数: 0

已访问节点:

# Kruskal算法

# 算法原理

Kruskal算法按照边的权值从小到大的顺序选择边,如果该边不会在MST中形成环,则将其加入MST。

# 算法步骤

  1. 将图中所有边按权值排序
  2. 依次选择权值最小的边
  3. 如果加入该边不会形成环,则将其加入MST
  4. 重复步骤2-3直到选择了V-1条边

# 复杂度分析

  • 时间复杂度:O(E log E),其中E是边数
  • 空间复杂度:O(V),其中V是顶点数

# 代码实现

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]:
            px, py = py, px
        self.parent[py] = px
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1
        return True

def kruskal(graph):
    n = len(graph)
    edges = []
    
    # 收集所有边
    for i in range(n):
        for j in range(i + 1, n):
            if graph[i][j]:
                edges.append((graph[i][j], i, j))
    
    # 按权值排序
    edges.sort()
    
    uf = UnionFind(n)
    mst_weight = 0
    edge_count = 0
    
    for weight, u, v in edges:
        if uf.union(u, v):
            mst_weight += weight
            edge_count += 1
            if edge_count == n - 1:
                break
    
    return mst_weight

# 示例

比较次数: 0

已访问节点:

# 应用场景

  1. 网络布线规划
  2. 电路设计
  3. 通信网络设计
  4. 供水管网规划

# 算法比较

算法 适用场景 时间复杂度 空间复杂度
Prim 稠密图 O(V^2) O(V)
Kruskal 稀疏图 O(E log E) O(V)