Topological sorting using Javascript DFS

Front End TechnologyWeb DevelopmentJavascript

A topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge UV from vertex u to vertex v, u comes before v in the ordering. This only makes sense in directed graphs.

There are many places where topological sort makes a lot of sense. For example, let's say you're following a recipe, in this, there are some steps that are must for going to the next steps. But some of these can be performed in parallel. In a similar fashion, during college when selecting courses, there are some prerequisites for more advanced courses which themselves may be prerequisites for further courses. For example −

Example

 /**
   *       CS101  CS102
   *       /       \ /
   *      CS204    CS340
   *       \      /| \
   *       CS380   | CS410
   *          \    | /
   *           CS540
*/

In the above graph, consider if you want to take the course on one level, You'll have to first take all courses it is connected to with from the level above it. Following are some possible topological sorts for the above graph −

CS101 -> CS204 -> CS102 -> CS340 -> CS410 -> CS380 -> CS540
CS102 -> CS101 -> CS340 -> CS204 -> CS410 -> CS380 -> CS540

Let us implement this in JavaScript. We'll write 2 functions, topological sort, and topologicalSortHelper to help recursively mark and explore the graph. 

Example

topologicalSortHelper(node, explored, s) {
   explored.add(node);
   // Marks this node as visited and goes on to the nodes
   // that are dependent on this node, the edge is node ----> n
   this.edges[node].forEach(n => {
      if (!explored.has(n)) {
         this.topologicalSortHelper(n, explored, s);
      }
   });
   // All dependencies are resolved for this node, we can now add
   // This to the stack.
   s.push(node);
}

topologicalSort() {
   // Create a Stack to keep track of all elements in sorted order
   let s = new Stack(this.nodes.length);
   let explored = new Set();

   // For every unvisited node in our graph, call the helper.
   this.nodes.forEach(node => {
      if (!explored.has(node)) {
         this.topologicalSortHelper(node, explored, s);
      }
   });

   while (!s.isEmpty()) {
      console.log(s.pop());
   }
}

You can test this using − 

Example

let g = new Graph();
g.addNode("A");
g.addNode("B");
g.addNode("C");
g.addNode("D");
g.addNode("E");
g.addNode("F");
g.addNode("G");

g.addDirectedEdge("A", "C");
g.addDirectedEdge("A", "B");
g.addDirectedEdge("A", "D");
g.addDirectedEdge("C", "D");
g.addDirectedEdge("D", "E");
g.addDirectedEdge("E", "F");
g.addDirectedEdge("B", "G");

g.topologicalSort();

The graph we created looks like − 

Example

/**
   *         A
   *       / | \
   *       C | B
   *       \ | |
   *         D G
   *         |
   *         E
   *         |
   *         F
*/

Output

This will give the output −

A
B
G
C
D
E
F
raja
Published on 28-Jun-2018 14:04:32
Advertisements