拓扑排序算法
字数 603 2025-10-26 23:21:19

拓扑排序算法

题目描述:给定一个有向无环图(DAG),包含n个节点(编号从0到n-1)和若干条有向边,要求生成该图的一个拓扑排序。拓扑排序是指对图中所有节点的一个线性排列,使得对于图中的每一条有向边(u → v),在排序中节点u都出现在节点v之前。

解题过程:

  1. 理解拓扑排序的核心概念
    拓扑排序只适用于有向无环图(DAG),如果图中存在环,则无法进行拓扑排序。拓扑排序的实际意义可以理解为任务之间的依赖关系,比如课程先修关系、任务执行顺序等。

  2. 算法实现思路
    我们使用Kahn算法(基于BFS的拓扑排序):

  • 计算每个节点的入度(指向该节点的边的数量)
  • 将所有入度为0的节点加入队列
  • 依次处理队列中的节点,将其邻居节点的入度减1
  • 如果邻居节点入度变为0,则加入队列
  • 记录出队顺序即为拓扑排序
  1. 详细步骤分解

步骤1:初始化数据结构

# 构建邻接表表示图
graph = [[] for _ in range(n)]
# 记录每个节点的入度
in_degree = [0] * n

步骤2:构建图和计算入度
对于每条边(u → v):

  • 将v添加到u的邻接表中
  • 将v的入度加1

步骤3:初始化队列

from collections import deque
queue = deque()
# 将所有入度为0的节点加入队列
for i in range(n):
    if in_degree[i] == 0:
        queue.append(i)

步骤4:执行拓扑排序

topo_order = []
while queue:
    node = queue.popleft()
    topo_order.append(node)
    
    # 遍历当前节点的所有邻居
    for neighbor in graph[node]:
        # 将邻居节点的入度减1
        in_degree[neighbor] -= 1
        # 如果邻居节点入度变为0,加入队列
        if in_degree[neighbor] == 0:
            queue.append(neighbor)

步骤5:验证结果
检查拓扑排序结果的长度:

  • 如果长度等于n,说明排序成功
  • 如果长度小于n,说明图中存在环,无法进行拓扑排序
  1. 完整代码示例
from collections import deque

def topological_sort(n, edges):
    # 初始化
    graph = [[] for _ in range(n)]
    in_degree = [0] * n
    
    # 构建图
    for u, v in edges:
        graph[u].append(v)
        in_degree[v] += 1
    
    # 拓扑排序
    queue = deque([i for i in range(n) if in_degree[i] == 0])
    result = []
    
    while queue:
        node = queue.popleft()
        result.append(node)
        
        for neighbor in graph[node]:
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                queue.append(neighbor)
    
    return result if len(result) == n else []  # 如果存在环返回空列表
  1. 算法复杂度分析
  • 时间复杂度:O(n + e),其中n是节点数,e是边数
  • 空间复杂度:O(n),用于存储入度数组和队列

这个算法保证了在有向无环图中能够找到合理的节点执行顺序,是解决依赖关系问题的经典方法。

拓扑排序算法 题目描述:给定一个有向无环图(DAG),包含n个节点(编号从0到n-1)和若干条有向边,要求生成该图的一个拓扑排序。拓扑排序是指对图中所有节点的一个线性排列,使得对于图中的每一条有向边(u → v),在排序中节点u都出现在节点v之前。 解题过程: 理解拓扑排序的核心概念 拓扑排序只适用于有向无环图(DAG),如果图中存在环,则无法进行拓扑排序。拓扑排序的实际意义可以理解为任务之间的依赖关系,比如课程先修关系、任务执行顺序等。 算法实现思路 我们使用Kahn算法(基于BFS的拓扑排序): 计算每个节点的入度(指向该节点的边的数量) 将所有入度为0的节点加入队列 依次处理队列中的节点,将其邻居节点的入度减1 如果邻居节点入度变为0,则加入队列 记录出队顺序即为拓扑排序 详细步骤分解 步骤1:初始化数据结构 步骤2:构建图和计算入度 对于每条边(u → v): 将v添加到u的邻接表中 将v的入度加1 步骤3:初始化队列 步骤4:执行拓扑排序 步骤5:验证结果 检查拓扑排序结果的长度: 如果长度等于n,说明排序成功 如果长度小于n,说明图中存在环,无法进行拓扑排序 完整代码示例 算法复杂度分析 时间复杂度:O(n + e),其中n是节点数,e是边数 空间复杂度:O(n),用于存储入度数组和队列 这个算法保证了在有向无环图中能够找到合理的节点执行顺序,是解决依赖关系问题的经典方法。