Topological order meaning

Topological sorting of vertices of a Directed Acyclic Graph is an ordering of the vertices $$v_1, v_2, ... v_n$$ in such a way, that if there is an edge directed towards vertex $$v_j$$ from vertex $$v_i$$, then $$v_i$$ comes before $$v_j$$. For example consider the graph given below:


A topological sorting of this graph is: $$1$$ $$2$$ $$3$$ $$4$$ $$5$$ There are multiple topological sorting possible for a graph. For the graph given above one another topological sorting is: $$1$$ $$2$$ $$3$$ $$5$$ $$4$$

In order to have a topological sorting the graph must not contain any cycles. In order to prove it, let's assume there is a cycle made of the vertices $$v_1, v_2, v_3 ... v_n$$. That means there is a directed edge between $$v_i$$ and $$v_{i+1}$$ $$[1 \le i \lt n]$$ and between $$v_n$$ and $$v_1$$. So now, if we do topological sorting then $$v_n$$ must come before $$v_1$$ because of the directed edge from $$v_n$$ to $$v_1$$. Clearly, $$v_{i+1}$$ will come after $$v_i$$, because of the directed from $$v_i$$ to $$v_{i+1}$$, that means $$v_1$$ must come before $$v_n$$. Well, clearly we've reached a contradiction, here. So topological sorting can be achieved for only directed and acyclic graphs.

Le'ts see how we can find a topological sorting in a graph. So basically we want to find a permutation of the vertices in which for every vertex $$v_i$$, all the vertices $$v_j$$ having edges coming out and directed towards $$v_i$$ comes before $$v_i$$. We'll maintain an array $$T$$ that will denote our topological sorting. So, let's say for a graph having $$N$$ vertices, we have an array $$in\_degree[]$$ of size $$N$$ whose $$i^{th}$$ element tells the number of vertices which are not already inserted in $$T$$ and there is an edge from them incident on vertex numbered $$i$$. We'll append vertices $$v_i$$ to the array $$T$$, and when we do that we'll decrease the value of $$in\_degree[v_j]$$ by $$1$$ for every edge from $$v_i$$ to $$v_j$$. Doing this will mean that we have inserted one vertex having edge directed towards $$v_j$$. So at any point we can insert only those vertices for which the value of $$in\_degree[]$$ is $$0$$. The algorithm using a BFS traversal is given below:

topological_sort[N, adj[N][N]] T = [] visited = [] in_degree = [] for i = 0 to N in_degree[i] = visited[i] = 0 for i = 0 to N for j = 0 to N if adj[i][j] is TRUE in_degree[j] = in_degree[j] + 1 for i = 0 to N if in_degree[i] is 0 enqueue[Queue, i] visited[i] = TRUE while Queue is not Empty vertex = get_front[Queue] dequeue[Queue] T.append[vertex] for j = 0 to N if adj[vertex][j] is TRUE and visited[j] is FALSE in_degree[j] = in_degree[j] - 1 if in_degree[j] is 0 enqueue[Queue, j] visited[j] = TRUE return T Let's take a graph and see the algorithm in action. Consider the graph given below:
Initially $$in\_degree[0] = 0$$ and $$T$$ is empty

So, we delete $$0$$ from $$Queue$$ and append it to $$T$$. The vertices directly connected to $$0$$ are $$1$$ and $$2$$ so we decrease their $$in\_degree[]$$ by $$1$$. So, now $$in\_degree[ 1 ] = 0$$ and so $$1$$ is pushed in $$Queue$$.


Next we delete $$1$$ from $$Queue$$ and append it to $$T$$. Doing this we decrease $$in\_degree[ 2 ]$$ by $$1$$, and now it becomes $$0$$ and $$2$$ is pushed into $$Queue$$.


So, we continue doing like this, and further iterations looks like as follows:

So at last we get our Topological sorting in $$T$$ i.e. : $$0$$, $$1$$, $$2$$, $$3$$, $$4$$, $$5$$

Solution using a DFS traversal, unlike the one using BFS, does not need any special $$in\_degree[]$$ array. Following is the pseudo code of the DFS solution:

T = [] visited = [] topological_sort[ cur_vert, N, adj[][] ]{ visited[cur_vert] = true for i = 0 to N if adj[cur_vert][i] is true and visited[i] is false topological_sort[i] T.insert_in_beginning[cur_vert] } The following image of shows the state of stack and of array $$T$$ in the above code for the same graph shown above.

Contributed by: Vaibhav Jaimini

Topological sort gives a linear ordering of vertices in a directed acyclic graph such that, for every directed edge a -> b, vertex ‘a’ comes before vertex ‘b’. Remember, a directed acyclic graph has at least one vertex with an in-degree of 0 and one vertex with an out-degree of 0.

There can be more than one topological ordering for a directed acyclic graph.

Kahn’s Algorithm

Kahn’s algorithm is used to perform a topological sort on a directed acyclic graph with time complexity of O[V+E]O[V + E]O[V+E] – where VVV is the number of vertices and EEE is the number of edges in the graph.

The steps below are involved in Kahn’s algorithm:

Auxiliary variables:

  1. An array [“temp”] to hold the result of the preprocessing stage.

  2. A variable [“visited”] to store the number of vertices that have been visited.

  3. A string [“result”] to hold the topological sort order.

  4. A queue.

Pre-processing:

Calculate the in-degree of each vertex of the graph and store them in the array “temp”.

Actual steps:

  1. Enqueue the vertices with the in-degree of 0.

  2. While the queue is not empty:

    2.1. Dequeue a vertex.

    2.2. Add this vertex to the result.

    2.3. Increment the “visited” variable by 1.

    2.4. Decrement the in-degree of all its neighboring vertices by 1 in the array “temp”.

    2.5 Enqueue the neighboring vertices with the in-degree of 0.

  3. If the value of the “visited” variable is equal to the number of vertices in the graph, then the graph is indeed directed and acyclic ​and the result will contain the topological sort for the graph.

The following illustration shows the algorithm in action:

A directed acyclic graph.

1 of 12

Topological sorting for Directed Acyclic Graph [DAG] is a linear ordering of vertices such that for every directed edge u v, vertex u comes before v in the ordering. Topological Sorting for a graph is not possible if the graph is not a DAG.

For example, a topological sorting of the following graph is “5 4 2 3 1 0”. There can be more than one topological sorting for a graph. For example, another topological sorting of the following graph is “4 5 2 3 1 0”. The first vertex in topological sorting is always a vertex with in-degree as 0 [a vertex with no incoming edges].
 

Topological Sorting vs Depth First Traversal [DFS]

In DFS, we print a vertex and then recursively call DFS for its adjacent vertices. In topological sorting, we need to print a vertex before its adjacent vertices. For example, in the given graph, the vertex ‘5’ should be printed before vertex ‘0’, but unlike DFS, the vertex ‘4’ should also be printed before vertex ‘0’. So Topological sorting is different from DFS. For example, a DFS of the shown graph is “5 2 3 1 0 4”, but it is not a topological sorting.



Recommended: Please solve it on “PRACTICE” first, before moving on to the solution.

Algorithm to find Topological Sorting: 

We recommend to first see the implementation of DFS. We can modify DFS to find Topological Sorting of a graph. In DFS, we start from a vertex, we first print it and then recursively call DFS for its adjacent vertices. In topological sorting, we use a temporary stack. We don’t print the vertex immediately, we first recursively call topological sorting for all its adjacent vertices, then push it to a stack. Finally, print contents of the stack. Note that a vertex is pushed to stack only when all of its adjacent vertices [and their adjacent vertices and so on] are already in the stack. 

Below image is an illustration of the above approach:

Following are the implementations of topological sorting. Please see the code for Depth First Traversal for a disconnected Graph and note the differences between the second code given there and the below code.

    void topologicalSortUtil[int v, bool visited[],

    void addEdge[int v, int w];

void Graph::addEdge[int v, int w]

void Graph::topologicalSortUtil[int v, bool visited[],

    for [i = adj[v].begin[]; i != adj[v].end[]; ++i]

            topologicalSortUtil[*i, visited, Stack];

void Graph::topologicalSort[]

    bool* visited = new bool[V];

    for [int i = 0; i < V; i++]

    for [int i = 0; i < V; i++]

            topologicalSortUtil[i, visited, Stack];

    while [Stack.empty[] == false] {

        cout

Chủ Đề