拓扑排序针对的是有向无环图(DAG):节点之间有”必须先做 A 再做 B”的依赖关系,需要给出一个不违反任何依赖的线性顺序。课程先修关系、构建系统的任务编排、make/cargo 依赖图都是这个套路。
Kahn 算法
直觉非常简单:
- 统计每个节点的入度(被多少箭头指向)
- 入度为 0 的节点没有先修依赖,可以立刻执行 → 放进队列
- 每次从队列取一个节点放到输出,并把它指向的所有节点的入度减 1
- 谁的入度被减到 0,就也入队
- 重复直到队列为空
如果走完后输出长度等于节点数,结果就是一个合法拓扑序;否则说明存在环。
复杂度
- 时间:O(V + E) — 每条边只被”消去”一次
- 空间:O(V)
在动画里看什么
- 节点圆圈下方的
in:N是当前入度,随出队过程下降 - 浅蓝:在 queue 里等待处理;深蓝:正在被处理;绿色:已经放入输出序列
- 边的箭头变灰表示这条依赖已经被消化
- 底部的
queue和order实时显示队列内容和当前拓扑序