图的拓扑排序使用顶点的离开时间
给定一个有向无环图(DAG),求该图的拓扑排序。
有向无环图 (DAG) 的拓扑排序是顶点的线性排序,因此对于每个有向边 uv,顶点 u 在排序中位于 v 之前。如果图不是 DAG,则无法对图进行拓扑排序。
例如,下图的拓扑排序是“5 4 2 3 1 0”。一个图可以有多个拓扑排序。例如,下图的另一种拓扑排序是“4 5 2 3 1 0”。
请注意,拓扑排序中的第一个顶点始终是入度为 0 的顶点(没有传入边的顶点)。对于上图,顶点 4 和 5 没有传入边。
我们已经讨论了使用堆栈和卡恩拓扑排序算法的基于 DFS 的算法。我们还讨论了如何在这里打印所有拓扑类型的 DAG。在这篇文章中,通过在 DFS 中引入顶点的到达和离开时间的概念,讨论了另一种基于 DFS 的方法来查找图的拓扑排序。
DFS中顶点的到达时间和离开时间是什么?
在 DFS 中, Arrival Time是第一次探索顶点的时间, Departure Time是我们已经探索了顶点的所有邻居并准备回溯的时间。
如何使用出发时间找到图的拓扑排序?
为了找到图的拓扑排序,我们从所有未访问的顶点一个接一个地运行 DFS。对于任何顶点,在探索其任何邻居之前,我们记录该顶点的到达时间,在探索该顶点的所有邻居之后,我们记录其离开时间。请注意,查找图的拓扑排序只需要出发时间,因此我们可以跳过顶点的到达时间。最后,在我们访问了图的所有顶点之后,我们按照出发时间递减的顺序打印顶点,这就是我们想要的顶点拓扑顺序。
下面是上述想法的 C++ 实现——
C++
// A C++ program to print topological sorting of a DAG
#include
using namespace std;
// Graph class represents a directed graph using adjacency
// list representation
class Graph {
int V; // No. of vertices
// Pointer to an array containing adjacency lists
list* adj;
public:
Graph(int); // Constructor
~Graph(); // Destructor
// function to add an edge to graph
void addEdge(int, int);
// The function to do DFS traversal
void DFS(int, vector&, vector&, int&);
// The function to do Topological Sort.
void topologicalSort();
};
Graph::Graph(int V)
{
this->V = V;
this->adj = new list[V];
}
Graph::~Graph() { delete[] this->adj; }
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v's list.
}
// The function to do DFS() and stores departure time
// of all vertex
void Graph::DFS(int v, vector& visited,
vector& departure, int& time)
{
visited[v] = true;
// time++; // arrival time of vertex v
for (int i : adj[v])
if (!visited[i])
DFS(i, visited, departure, time);
// set departure time of vertex v
departure[time++] = v;
}
// The function to do Topological Sort. It uses DFS().
void Graph::topologicalSort()
{
// vector to store departure time of vertex.
vector departure(V, -1);
// Mark all the vertices as not visited
vector visited(V, false);
int time = 0;
// perform DFS on all unvisited vertices
for (int i = 0; i < V; i++) {
if (visited[i] == 0) {
DFS(i, visited, departure, time);
}
}
// print the topological sort
for (int i = V - 1; i >= 0; i--)
cout << departure[i] << " ";
}
// Driver program to test above functions
int main()
{
// Create a graph given in the above diagram
Graph g(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
cout << "Topological Sort of the given graph is \n";
g.topologicalSort();
return 0;
}
Python3
# A Python3 program to print topological sorting of a DAG
def addEdge(u, v):
global adj
adj[u].append(v)
# The function to do DFS() and stores departure time
# of all vertex
def DFS(v):
global visited, departure, time
visited[v] = 1
for i in adj[v]:
if visited[i] == 0:
DFS(i)
departure[time] = v
time += 1
# The function to do Topological Sort. It uses DFS().
def topologicalSort():
# perform DFS on all unvisited vertices
for i in range(V):
if(visited[i] == 0):
DFS(i)
# Print vertices in topological order
for i in range(V - 1, -1, -1):
print(departure[i], end = " ")
# Driver code
if __name__ == '__main__':
# Create a graph given in the above diagram
V,time, adj, visited, departure = 6, 0, [[] for i in range(7)], [0 for i in range(7)],[-1 for i in range(7)]
addEdge(5, 2)
addEdge(5, 0)
addEdge(4, 0)
addEdge(4, 1)
addEdge(2, 3)
addEdge(3, 1)
print("Topological Sort of the given graph is")
topologicalSort()
# This code is contributed by mohit kumar 29
Javascript
Topological Sort of the given graph is
5 4 2 3 1 0
上述解决方案的时间复杂度为 O(V + E)。