什么是拓扑排序

时间:2018-03-26 00:46:54

标签: graph topological-sort

我在网上查了很多例子并观看了一段YouTube视频,但我仍然对拓扑排序有点迷失。据我所知,你应该从访问过的和未访问过的队列开始,并在完成访问节点的所有子节点后获得拓扑排序顺序?

2 个答案:

答案 0 :(得分:0)

拓扑排序是节点的线性排序,其中对于每个有向边“ a-> b”,在排序中,“ a”位于“ b”之前。由于必须对边进行定向,因此必须对有向图进行拓扑排序,并且图也必须是非循环的(它们不能包含循环)。这是称为DAG(有向无环图)的图的特殊子集。

Here is an example of what it looks like, notice all edges (arrows) go left to right

找到拓扑排序的最佳方法是将DFS与临时Stack(而不是Queue)一起使用。您的理解是紧密的,但并不完全相同。由于DFS在图上运行,因此您也必须先探索该节点的所有子节点,然后再将该节点推入临时堆栈。这是该算法的递归元素起作用的地方。由于您不希望在探索其子节点之前将其压入堆栈,因此必须等到该算法在子节点上完成运行之后再进行操作。通过实现堆栈,从顶部弹出的第一个节点将没有指向它的边,而从弹出的最后一个节点将没有来自它的边。如果我们使用队列,那将是另一种方式。

您可以使用第二个堆栈,并在将其添加到临时堆栈中以进行内务处理后从中删除节点。一旦所有节点都在临时堆栈上,将它们逐一弹出来打印它们,您将获得给定图的拓扑排序。

答案 1 :(得分:0)

拓扑排序意味着你会得到一份工作列表和先决条件列表,你必须弄清楚工作的顺序。

工作 = [1,2,3] 先决条件 = [[1,2], [1, 3], [3,2]]

result = [1,3,2] 应该是作业执行的顺序。 这里的 [1,2] 表示在作业 1 完成之前无法启动作业 2(作业 1 是先决条件)。

因此,您可以使用简单的深度优先搜索(图形遍历算法)。其中你可以有一个用 JobVertex 命名的自定义类

class JobVertex {
   int job;
   List<JobVertex> preRequisites;
   boolean inProgress; 
   boolean visited;}

最初,inProgress 和visited 标志都可以设置为false。 inProgress标志用于检测循环(因为对工作图进行拓扑排序必须是DAG)

List<Integer> result = new ArrayList<>();

result 是将添加我们订购的作业的最终列表。 dfs(node, result) 方法看起来像这样,您可以从任何节点开始,然后以递归方式遍历其先决条件,并在每次迭代时更新标志。

时间复杂度可以与 dfs (v + e) 相同,其中 v 对应顶点,e 分别对应边。