GFG App
Open App
Browser
Continue

# Kahn’s Algorithm vs DFS Approach: A Comparative Analysis

Topological sorting is a common problem in computer science that involves arranging the vertices of a directed acyclic graph (DAG) in a linear order such that for every directed edge (u, v), vertex u comes before vertex v in the ordering.

Two important methods to solve are:

• Kahn’s Algorithm
• Depth-First Search (DFS) Algorithm

Let us take the following example as input for both algorithms:

Directed Acyclic Graph

### Kahn’s Algorithm:

Kahn’s Algorithm is a topological sorting algorithm that uses a queue-based approach to sort vertices in a DAG. It starts by finding vertices that have no incoming edges and adds them to a queue. It then removes a vertex from the queue and adds it to the sorted list. The algorithm continues this process, removing vertices with no incoming edges until all vertices have been sorted.

Below is the implementation of the Kahn’s approach:

## C++

 `// C++ Implementation` `#include ` `using` `namespace` `std;` `class` `Solution {`   `public``:` `    ``// Topological sort using bfs is called` `    ``// Kahn's Algorithm` `    ``void` `topo_sort(vector<``int``> adj[], ``int` `n)` `    ``{` `        ``// Here concept of indegree used` `        ``// as it represents number of incoming` `        ``// edges on a node` `        ``vector<``int``> indegree(n, 0);` `        ``// Code for make indegree` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``for` `(``auto` `it : adj[i]) {` `                ``indegree[it]++;` `            ``}` `        ``}`   `        ``vector<``int``> ans;` `        ``queue<``int``> qrr;` `        ``// Initially insert elements who has` `        ``// indegree 0` `        ``for` `(``int` `i = 0; i < n; i++) {`   `            ``if` `(indegree[i] == 0) {` `                ``qrr.push(i);` `            ``}` `        ``}`   `        ``while` `(!qrr.empty()) {` `            ``// push those elements in queue which` `            ``// poses 0 indegree` `            ``int` `node = qrr.front();`   `            ``qrr.pop();` `            ``ans.push_back(node);` `            ``for` `(``auto` `it : adj[node]) {` `                ``indegree[it]--;` `                ``if` `(indegree[it] == 0) {` `                    ``qrr.push(it);` `                ``}` `            ``}` `        ``}` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``cout << ans[i] << ``" "``;` `        ``}` `    ``}` `};`   `// Function to add  edge` `void` `addEdge(vector<``int``> adj[], ``int` `u, ``int` `v)` `{` `    ``adj[u].push_back(v);` `}`   `// Driver code` `int` `main()` `{` `    ``int` `n = 6;` `    ``vector<``int``> adj[n];` `    ``addEdge(adj, 5, 0);` `    ``addEdge(adj, 5, 2);` `    ``addEdge(adj, 2, 0);` `    ``addEdge(adj, 2, 3);` `    ``addEdge(adj, 3, 0);` `    ``addEdge(adj, 3, 1);` `    ``addEdge(adj, 1, 0);` `    ``addEdge(adj, 4, 0);` `    ``addEdge(adj, 4, 1);` `    ``Solution s1;`   `    ``// Function call` `    ``s1.topo_sort(adj, n);` `    ``return` `0;` `}`

## Java

 `import` `java.util.*;`   `class` `Solution {`   `    ``public` `void` `topo_sort(List[] adj, ``int` `n)` `    ``{` `        ``List indegree` `            ``= ``new` `ArrayList<>(Collections.nCopies(n, ``0``));`   `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``for` `(``int` `it : adj[i]) {` `                ``indegree.set(it, indegree.get(it) + ``1``);` `            ``}` `        ``}`   `        ``List ans = ``new` `ArrayList<>();` `        ``Queue qrr = ``new` `LinkedList<>();`   `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``if` `(indegree.get(i) == ``0``) {` `                ``qrr.add(i);` `            ``}` `        ``}`   `        ``while` `(!qrr.isEmpty()) {` `            ``int` `node = qrr.poll();` `            ``ans.add(node);`   `            ``for` `(``int` `it : adj[node]) {` `                ``indegree.set(it, indegree.get(it) - ``1``);`   `                ``if` `(indegree.get(it) == ``0``) {` `                    ``qrr.add(it);` `                ``}` `            ``}` `        ``}`   `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``System.out.print(ans.get(i) + ``" "``);` `        ``}` `    ``}` `}`   `class` `Main {`   `    ``@SuppressWarnings``(``"unchecked"``)` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``int` `n = ``6``;` `        ``List[] adj = ``new` `ArrayList[n];`   `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``adj[i] = ``new` `ArrayList<>();` `        ``}`   `        ``addEdge(adj, ``5``, ``0``);` `        ``addEdge(adj, ``5``, ``2``);` `        ``addEdge(adj, ``2``, ``0``);` `        ``addEdge(adj, ``2``, ``3``);` `        ``addEdge(adj, ``3``, ``0``);` `        ``addEdge(adj, ``3``, ``1``);` `        ``addEdge(adj, ``1``, ``0``);` `        ``addEdge(adj, ``4``, ``0``);` `        ``addEdge(adj, ``4``, ``1``);`   `        ``Solution s1 = ``new` `Solution();` `        ``s1.topo_sort(adj, n);` `    ``}`   `    ``private` `static` `void` `addEdge(List[] adj, ``int` `u,` `                                ``int` `v)` `    ``{` `        ``adj[u].add(v);` `    ``}` `}`

## Python3

 `from` `typing ``import` `List``, Deque` `from` `collections ``import` `deque`   `class` `Solution:` `    ``def` `topo_sort(``self``, adj: ``List``[``int``], n: ``int``) ``-``> ``List``[``int``]:` `        ``# Create a list to store the in-degree of each node` `        ``indegree ``=` `[``0``] ``*` `n` `        `  `        ``# Calculate the in-degree of each node` `        ``for` `i ``in` `range``(n):` `            ``for` `j ``in` `adj[i]:` `                ``indegree[j] ``+``=` `1` `        `  `        ``# Create a queue to store nodes with in-degree 0` `        ``q ``=` `deque()` `        ``for` `i ``in` `range``(n):` `            ``if` `indegree[i] ``=``=` `0``:` `                ``q.append(i)` `        `  `        ``# Perform topological sorting using BFS` `        ``ans ``=` `[]` `        ``while` `q:` `            ``node ``=` `q.popleft()` `            ``ans.append(node)` `            ``for` `i ``in` `adj[node]:` `                ``indegree[i] ``-``=` `1` `                ``if` `indegree[i] ``=``=` `0``:` `                    ``q.append(i)` `        `  `        ``# Return the sorted nodes` `        ``return` `ans`   `# Function to add an edge` `def` `addEdge(adj: ``List``[``int``], u: ``int``, v: ``int``) ``-``> ``None``:` `    ``adj[u].append(v)`   `# Driver code` `if` `__name__ ``=``=` `"__main__"``:` `    ``n ``=` `6` `    ``adj ``=` `[[] ``for` `_ ``in` `range``(n)]` `    ``addEdge(adj, ``5``, ``0``)` `    ``addEdge(adj, ``5``, ``2``)` `    ``addEdge(adj, ``2``, ``0``)` `    ``addEdge(adj, ``2``, ``3``)` `    ``addEdge(adj, ``3``, ``0``)` `    ``addEdge(adj, ``3``, ``1``)` `    ``addEdge(adj, ``1``, ``0``)` `    ``addEdge(adj, ``4``, ``0``)` `    ``addEdge(adj, ``4``, ``1``)` `    ``s ``=` `Solution()`   `    ``# Function call` `    ``print``(s.topo_sort(adj, n))`

## C#

 `// C# Implementation`   `using` `System;` `using` `System.Collections.Generic;`   `class` `Solution {` `    ``// Topological sort using bfs is called` `    ``// Kahn's Algorithm` `    ``public` `void` `TopoSort(List<``int``>[] adj, ``int` `n)` `    ``{` `        ``// Here concept of indegree used` `        ``// as it represents number of incoming` `        ``// edges on a node` `        ``int``[] indegree = ``new` `int``[n];` `        ``// Code for make indegree` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``foreach``(``int` `it ``in` `adj[i]) { indegree[it]++; }` `        ``}`   `        ``List<``int``> ans = ``new` `List<``int``>();` `        ``Queue<``int``> qrr = ``new` `Queue<``int``>();`   `        ``// Initially insert elements who has` `        ``// indegree 0` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``if` `(indegree[i] == 0) {` `                ``qrr.Enqueue(i);` `            ``}` `        ``}`   `        ``while` `(qrr.Count > 0) {` `            ``// push those elements in queue which` `            ``// poses 0 indegree` `            ``int` `node = qrr.Dequeue();`   `            ``ans.Add(node);` `            ``foreach``(``int` `it ``in` `adj[node])` `            ``{` `                ``indegree[it]--;` `                ``if` `(indegree[it] == 0) {` `                    ``qrr.Enqueue(it);` `                ``}` `            ``}` `        ``}`   `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``Console.Write(ans[i] + ``" "``);` `        ``}` `    ``}` `}`   `// Driver code` `public` `class` `GFG {` `    ``static` `void` `Main(``string``[] args)` `    ``{` `        ``int` `n = 6;` `        ``List<``int``>[] adj = ``new` `List<``int``>[ n ];` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``adj[i] = ``new` `List<``int``>();` `        ``}` `        ``adj[5].Add(0);` `        ``adj[5].Add(2);` `        ``adj[2].Add(0);` `        ``adj[2].Add(3);` `        ``adj[3].Add(0);` `        ``adj[3].Add(1);` `        ``adj[1].Add(0);` `        ``adj[4].Add(0);` `        ``adj[4].Add(1);`   `        ``Solution s1 = ``new` `Solution();`   `        ``// Function call` `        ``s1.TopoSort(adj, n);` `    ``}` `}`

## Javascript

 `// Javadcript code addition `   `class Solution {` `    ``topoSort(adj, n) {` `        ``let indegree = ``new` `Array(n).fill(0);` `        ``let ans = [];` `        ``let qrr = [];` `        `  `        ``// Code for make indegree` `        ``for` `(let i = 0; i < n; i++) {` `            ``for` `(let it of adj[i]) {` `                ``indegree[it]++;` `            ``}` `        ``}` `        `  `        ``// Initially insert elements who has indegree 0` `        ``for` `(let i = 0; i < n; i++) {` `            ``if` `(indegree[i] == 0) {` `                ``qrr.push(i);` `            ``}` `        ``}`   `        ``while` `(qrr.length > 0) {` `            ``let node = qrr.shift();` `            ``ans.push(node);` `            ``for` `(let it of adj[node]) {` `                ``indegree[it]--;` `                ``if` `(indegree[it] == 0) {` `                    ``qrr.push(it);` `                ``}` `            ``}` `        ``}` `        `  `        ``for` `(let i = 0; i < n; i++) {` `            ``process.stdout.write(ans[i] + ``" "``);` `        ``}` `    ``}` `}`   `// Function to add edge` `function` `addEdge(adj, u, v) {` `    ``adj[u].push(v);` `}`   `// Driver code` `let n = 6;` `let adj = Array.from({ length: n }, () => []);` `addEdge(adj, 5, 0);` `addEdge(adj, 5, 2);` `addEdge(adj, 2, 0);` `addEdge(adj, 2, 3);` `addEdge(adj, 3, 0);` `addEdge(adj, 3, 1);` `addEdge(adj, 1, 0);` `addEdge(adj, 4, 0);` `addEdge(adj, 4, 1);` `let s1 = ``new` `Solution();`   `// Function call` `s1.topoSort(adj, n);`   `// The code is contributed by Nidhi goel.`

Output

`4 5 2 3 1 0 `

Time Complexity: O( V + E)
Auxiliary Space: O(V)

### DFS Approach:

DFS Approach is a recursive algorithm that performs a depth-first search on the DAG. It starts at a vertex, explores as far as possible along each branch before backtracking, and marks visited vertices. During the DFS traversal, vertices are added to a stack in the order they are visited. Once the DFS traversal is complete, the stack is reversed to obtain the topological ordering.

Below is the implementation of the DFS approach:

## C++

 `#include ` `using` `namespace` `std;` `class` `Solution {`   `    ``// Topo sort only exists in DAGs i.e.` `    ``// Direct Acyclic graph` `    ``void` `dfs(vector<``int``> adj[], vector<``int``>& vis, ``int` `node,` `             ``int` `n, stack<``int``>& stck)` `    ``{` `        ``vis[node] = 1;` `        ``for` `(``auto` `it : adj[node]) {` `            ``if` `(!vis[it]) {` `                ``dfs(adj, vis, it, n, stck);` `            ``}` `        ``}` `        ``stck.push(node);` `    ``}`   `public``:` `    ``// During the traversal u must` `    ``// be visited before v` `    ``stack<``int``> topo_sort(vector<``int``> adj[], ``int` `n)` `    ``{` `        ``vector<``int``> vis(n, 0);`   `        ``// using stack ADT` `        ``stack<``int``> stck;` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``if` `(!vis[i]) {` `                ``dfs(adj, vis, i, n, stck);` `            ``}` `        ``}` `        ``return` `stck;` `    ``}` `};`   `void` `addEdge(vector<``int``> adj[], ``int` `u, ``int` `v)` `{` `    ``adj[u].push_back(v);` `}`   `// Drivers code` `int` `main()` `{` `    ``int` `n = 6;` `    ``vector<``int``> adj[n];` `    ``addEdge(adj, 5, 0);` `    ``addEdge(adj, 5, 2);` `    ``addEdge(adj, 2, 0);` `    ``addEdge(adj, 2, 3);` `    ``addEdge(adj, 3, 0);` `    ``addEdge(adj, 3, 1);` `    ``addEdge(adj, 1, 0);` `    ``addEdge(adj, 4, 0);` `    ``addEdge(adj, 4, 1);` `    ``Solution s1;` `    ``stack<``int``> ans = s1.topo_sort(adj, n);` `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``int` `n = ans.top();` `        ``ans.pop();` `        ``cout << n << ``" "``;` `    ``}` `    ``return` `0;` `}`

Output

`5 4 2 3 1 0 `

Time Complexity: O( V + E)
Auxiliary Space: O(V)

Comparative Analysis :

• Both Kahn’s Algorithm and DFS Approach have their strengths and weaknesses. Kahn’s Algorithm is easy to implement and guarantees a topological sort, but it can be slower for large graphs. On the other hand, DFS Approach is more efficient for larger graphs, but it requires more memory and can be more complex to implement.
• Kahn’s Algorithm is a good choice when dealing with smaller graphs, where simplicity and correctness are more important than performance. It is also useful in situations where you need to detect cycles in the graph. If a cycle is detected during the sorting process, the algorithm will terminate early and report that the graph is not a DAG.
• DFS Approach, on the other hand, is a better choice when dealing with larger graphs where performance is more important than simplicity. It is also useful in situations where you need to find a topological sort quickly, and memory is not a constraint.

### Advantages of Kahn’s Algorithm over the DFS Approach:

• Guaranteed to find a topological ordering if one exists.
• Simple and easy to implement.
• Works well for small and medium-sized DAGs.

### Disadvantages of Kahn’s Algorithm compared to the DFS Approach:

• Can be slower than DFS Approach for large DAGs.
• Requires more memory than DFS Approach.
• Requires a queue data structure, which may not be available in some programming languages.

### Advantages of the DFS Approach over Kahn’s Algorithm:

• Can be faster for larger DAGs.
• Requires less memory than Kahn’s Algorithm.
• Does not require a queue data structure.

### Disadvantages of the DFS Approach compared to Kahn’s Algorithm:

• May not find a topological ordering if the graph has cycles.
• More complex to implement than Kahn’s Algorithm.
• Can be less efficient for small and medium-sized DAGs.

### Conclusion:

In conclusion, both Kahn’s Algorithm and DFS Approach are effective algorithms for topological sorting in DAGs. The choice between the two depends on the size of the graph, the available memory, and the required performance. In general, Kahn’s Algorithm is simpler and more reliable, but DFS Approach can be more efficient for larger graphs. Both algorithms have their strengths and weaknesses, and the best approach depends on the specific requirements of the problem at hand.

My Personal Notes arrow_drop_up