1. 基本概念
- A topological sort is an ordering of vertices in a directed acyclic graph, such that if there is a path from vi to vj, then vj appears after vi in the ordering.
- It is clear that a topological ordering is not possible if the graph has a cycle, since for two vertices v and w on the cycle, v precedes w and w precedes v. Furthermore, the ordering is not necessarily unique; any legal ordering will do.
有向的拓扑排序需要记住最关键的几点:
- 如果 ,那么 需要在 后面
- 进行拓扑排序的有向图一定是无圈的(DAG),否则破坏第一条性质。
- 拓扑排序的结果不唯一,可能有多种答案。
- 拓扑排序的有向图可以是强连通、弱联通或者不连通
理解这几点很关键,最后一点是笔者总结的。给我们任意序列,我们只需要只需要根据第一条性质就再结合图判断其是否为拓扑排序,注意任意两个节点之间并不一定连通。
2. Kahn’s algorithm
DSAA这里有点冗余,直接看维基百科:
- The usual algorithms for topological sorting have running time linear in the number of nodes plus the number of edges, asymptotically, .
L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edge
while S is non-empty do
remove a node n from S
add n to tail of L
for each node m with an edge e from n to m do
remove edge e from the graph
if m has no other incoming edges then
insert m into S
if graph has edges then
return error (graph has at least one cycle)
else
return L (a topologically sorted order)
上面为维基官网给出的伪代码,该伪代码本身已经很好的阐述了算法的过程,现在笔者再总结下:
- 使用了一个Set存储入度为0的节点,(Set可以为Queue,Stack,总之可以做到 插入,删除的数据结构都可以,是否常数时间随机访问无所谓)
- 刚开始需要遍历图,时间复杂度为 (邻接表的实现),将所有的入度为0的节点放入Set中。
- 循环从Set中取出一个入度为0的顶点,将其放入结果(任意数据结构)中并删除所有与它相关的边,删除的时候就要更新入度信息,将入度为0的节点放入Set中。
- 当图有cycle时,whlie循环结束时,图还是存在节点和边,此时输出“有环的结论”,否则输出结果。
算法时间复杂度
从上面的过程来看,遍历了整个图的所有顶点和边。所以时间复杂度为 ,空间复杂度因为需要额外的Set及Output结果,所以为 。(Set最大为N)
3. 最后
在以后刷leetcode
时,再考虑相关的实现。现在为了更加形象的描述上述算法的本质,画个草图:
上面的DAG每次算法的执行会依次输出:1,2,3,4。而下面的DG图输出1之后就提示有环存在了,这下够直观了吧。