拓扑排序

2024 年 8 月 28 日 | 阅读 10 分钟

有向图的拓扑排序或拓扑顺序是其顶点的一种线性排序,其中对于从顶点 u 到顶点 v 的每个有向边 uv,u 在排序中出现在 v 之前。例如,图的顶点可以表示要完成的工作,边可以反映一项工作必须在另一项工作之前完成的要求。

在这种情况下,拓扑排序只是一个合法的任务序列。拓扑排序是一种图遍历,其中每个节点 v 仅在其所有依赖项都被访问后才被访问。如果图不包含有向循环,则它是一个有向无环图。任何 DAG 都有至少一个拓扑排序,并且存在以线性时间构建任何 DAG 的拓扑排序的技术。

拓扑排序有许多应用,特别是在排名问题中,如反馈弧集。即使 DAG 包含不连通的组件,拓扑排序也是可能的。

Java 代码

现在让我们编写一个拓扑排序的 Java 示例代码。

输出

上面的 Java 代码产生以下输出。

Please Choose one of the Operations::
1. To create a Directed Acyclic Graph (DAG) for topological sort.
2. To print the result of the topological sort.
1
Directed Acyclic Graph (DAG) created successfully.
Do you want to continue (Type y or n)
y
Please Choose one of the Operations::
1. To create a Directed Acyclic Graph (DAG) for topological sort.
2. To print the result of the topological sort.
2
The result after topological sort of the Directed Acyclic Graph
25  20 15 10 5  0 
Do you want to continue (Type y or n)
n

因此,在上面的 Java 代码中,我们创建了一个名为 Graph 的类,它将使用邻接表表示法来表示有向图。还编写了执行各种操作(如在图中添加新节点)的不同成员函数。编写了一个名为 topologicalSort() 的函数来执行图的拓扑排序的实际任务。topologicalSort() 函数内部调用了一个名为 topologicalSortUtil() 的递归函数,该函数包含图的拓扑排序的实际逻辑。一旦在图上执行了拓扑排序,由于拓扑操作,图的节点将被打印出来。

C++ 代码

让我们看看 C++ 代码,

输出

上面的 C++ 代码产生以下输出。

Directed Acyclic Graph (DAG) created successfully.
The result of topological Sort is
5 4 2 3 1 0 

因此,在上面的 C++ 代码中,我们创建了一个名为 Graph 的类,它将使用邻接表表示法来表示有向图。还编写了执行各种操作(如在图中添加新节点)的不同成员函数。然后编写了一个名为 topologicalSort() 的函数来执行图的拓扑排序的实际任务。topologicalSort() 函数内部调用了一个名为 topologicalSortUtil() 的递归函数,该函数包含图的拓扑排序的实际逻辑。一旦在图上执行了拓扑排序,由于拓扑操作,图的节点将被打印出来。

拓扑排序的优点

拓扑排序主要用于根据作业的依赖关系进行调度。指令调度、电子表格中重新计算公式值时公式单元格评估的排序、逻辑综合、确定 make 文件中要执行的编译任务顺序、数据序列化以及链接器中符号依赖关系的解析都是这类应用在计算机科学中的示例。

  • 在图中查找循环:只有有向无环图可以进行拓扑排序(DAG)。无法对循环图进行拓扑排序。
  • 操作系统死锁检测:当一个进程等待另一个进程持有请求的资源时,就会发生死锁。
  • 依赖解析:拓扑排序已被证明在依赖解析中非常有用。
  • 句子排序:设 n 个文档 D={d1,d2...,dn},文档中的句子数为 vi,其中 ∀i, vi>=1。假设随机顺序 o=[o1,....ovi] 和一组随机顺序的 vi 个句子为 {So1, So2,..., Sovi}。那么任务是找到正确的句子顺序 o*={o*1,...o*vi}。一组约束 Ci 表示 di 中每对句子之间的相对顺序,其中 |Ci|=(vi*(vi-1))/2。例如,如果一个文档有三个句子按正确顺序 s1 < s2 < s3,那么我们有三组约束 {s1 < s2, s1 < s3, s2 < s3}
    句子的顺序可以用 DAG 表示。这里句子 (Si) 表示顶点,边表示句子之间的顺序。例如,如果我们在 S1 到 S2 之间有一个有向边,那么 S1 必须在 S2 之前。拓扑排序可以生成这些句子的排序(句子排序)。
  • 关键路径分析:一种项目管理方法,称为关键路径分析。它用于确定项目应花费的时间以及每个行动对其他行动的依赖程度。一个活动之前可能有一些先行活动。在开始新活动之前,所有之前的活动都必须完成。
  • 课程安排问题:拓扑排序已被证明在解决课程安排问题中非常有用。
  • 其他应用,如制造工作流、数据序列化和上下文无关语法。

下一主题三叉搜索树