拓扑排序是一种对有向无环图(DAG)进行排序的算法,其目的是将图中的所有顶点线性排列,使得对于每一条有向边 ,顶点 在顶点 之前。换句话说,拓扑排序确保了所有的依赖关系都被满足。
拓扑排序的应用场景包括:
- 任务调度:在有依赖关系的任务中,确保先完成依赖的任务再进行后续任务。
- 编译顺序:在编译程序时,确保先编译依赖的模块。
- 课程安排:在学习课程时,确保先学习先修课程。
拓扑排序的常用算法有两种:
-
Kahn 算法:通过计算每个顶点的入度,逐步将入度为 0 的顶点加入排序结果,并更新其邻接顶点的入度。
L ← 包含已排序的元素的列表,目前为空 S ← 入度为零的节点的集合 当 S 非空时: 将节点n从S移走 将n加到L尾部 选出任意起点为n的边e = (n,m),移除e。如m没有其它入边,则将m加入S。 重复上一步。 如图中有剩余的边则: return error (图中至少有一个环) 否则: return L (L为图的拓扑排序)
-
深度优先搜索(DFS):通过对图进行DFS遍历,记录每个顶点的完成时间,最后反转完成时间的顺序得到拓扑排序。
L ← 一个空的 用来存放已排序的节点的列表 当图中存在未永久标记的节点时: 选出任何未永久标记的节点n visit(n) function visit(节点 n) 如n被永久标记: return 如n被临时标记: stop (不是定向无环图,至少有一个环) 将n临时标记 对于每一个以n为起点的边(n,m): visit(m) 去掉n的临时标记 将n永久标记 在L的起始位置插入n(如L已有内容 后移它们以空出起始位置)