拓扑排序的Kahn算法
字数 950 2025-11-15 09:19:16

拓扑排序的Kahn算法

题目描述
拓扑排序是针对有向无环图(DAG)的一种线性排序,使得对于图中的每一条有向边(u, v),u在排序中都出现在v之前。Kahn算法是一种基于贪心策略的拓扑排序算法,通过不断移除入度为0的顶点来实现排序。

知识要点

  • 拓扑排序只适用于有向无环图
  • 入度:指向某个顶点的边的数量
  • 算法核心:维护入度为0的顶点集合
  • 时间复杂度:O(V+E),其中V是顶点数,E是边数

解题过程

  1. 计算每个顶点的入度

    • 初始化一个数组indegree,长度为顶点数V,所有元素初始化为0
    • 遍历图中的所有边,对于每条边u→v,将顶点v的入度加1
    • 示例:对于边A→B,B的入度增加1;对于边A→C,C的入度增加1
  2. 初始化队列

    • 创建一个队列(或优先队列,如果需要特定顺序)
    • 遍历所有顶点,将所有入度为0的顶点加入队列
    • 这些顶点是当前没有前驱的顶点,可以立即排在结果序列中
  3. 处理队列中的顶点

    • 从队列中取出一个顶点u,将其加入结果列表
    • 遍历u的所有邻接顶点v(即u→v的边)
    • 对于每个邻接顶点v,将其入度减1
    • 如果v的入度变为0,将v加入队列
    • 重复此过程直到队列为空
  4. 检查结果

    • 如果结果列表中的顶点数等于图中的顶点数,说明拓扑排序成功
    • 如果结果列表中的顶点数小于图中的顶点数,说明图中存在环,无法进行拓扑排序

算法示例
考虑有向图:A→B, A→C, B→D, C→D

步骤:

  1. 计算入度:A:0, B:1, C:1, D:2
  2. 初始队列:[A](只有A的入度为0)
  3. 处理A:结果=[A],更新B入度→0,C入度→0,队列=[B,C]
  4. 处理B:结果=[A,B],更新D入度→1,队列=[C]
  5. 处理C:结果=[A,B,C],更新D入度→0,队列=[D]
  6. 处理D:结果=[A,B,C,D]
  7. 最终拓扑排序:A→B→C→D 或 A→C→B→D

关键点

  • 队列保证了顶点的处理顺序
  • 入度的动态更新确保了依赖关系的正确性
  • 结果验证可以检测图中是否存在环

应用场景

  • 任务调度(有依赖关系的任务排序)
  • 课程安排(先修课程关系)
  • 编译顺序(源文件依赖关系)
  • 工作流管理

Kahn算法通过简单的入度管理和队列操作,高效地解决了DAG的拓扑排序问题,是处理有依赖关系排序问题的经典算法。

拓扑排序的Kahn算法 题目描述 : 拓扑排序是针对有向无环图(DAG)的一种线性排序,使得对于图中的每一条有向边(u, v),u在排序中都出现在v之前。Kahn算法是一种基于贪心策略的拓扑排序算法,通过不断移除入度为0的顶点来实现排序。 知识要点 : 拓扑排序只适用于有向无环图 入度:指向某个顶点的边的数量 算法核心:维护入度为0的顶点集合 时间复杂度:O(V+E),其中V是顶点数,E是边数 解题过程 : 计算每个顶点的入度 初始化一个数组indegree,长度为顶点数V,所有元素初始化为0 遍历图中的所有边,对于每条边u→v,将顶点v的入度加1 示例:对于边A→B,B的入度增加1;对于边A→C,C的入度增加1 初始化队列 创建一个队列(或优先队列,如果需要特定顺序) 遍历所有顶点,将所有入度为0的顶点加入队列 这些顶点是当前没有前驱的顶点,可以立即排在结果序列中 处理队列中的顶点 从队列中取出一个顶点u,将其加入结果列表 遍历u的所有邻接顶点v(即u→v的边) 对于每个邻接顶点v,将其入度减1 如果v的入度变为0,将v加入队列 重复此过程直到队列为空 检查结果 如果结果列表中的顶点数等于图中的顶点数,说明拓扑排序成功 如果结果列表中的顶点数小于图中的顶点数,说明图中存在环,无法进行拓扑排序 算法示例 : 考虑有向图:A→B, A→C, B→D, C→D 步骤: 计算入度:A:0, B:1, C:1, D:2 初始队列:[ A ](只有A的入度为0) 处理A:结果=[ A],更新B入度→0,C入度→0,队列=[ B,C ] 处理B:结果=[ A,B],更新D入度→1,队列=[ C ] 处理C:结果=[ A,B,C],更新D入度→0,队列=[ D ] 处理D:结果=[ A,B,C,D ] 最终拓扑排序:A→B→C→D 或 A→C→B→D 关键点 : 队列保证了顶点的处理顺序 入度的动态更新确保了依赖关系的正确性 结果验证可以检测图中是否存在环 应用场景 : 任务调度(有依赖关系的任务排序) 课程安排(先修课程关系) 编译顺序(源文件依赖关系) 工作流管理 Kahn算法通过简单的入度管理和队列操作,高效地解决了DAG的拓扑排序问题,是处理有依赖关系排序问题的经典算法。