Skip to content

Commit 3e9c9e4

Browse files
committed
feat: added topological sorting algorithm
1 parent 74e8ec2 commit 3e9c9e4

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed

Graphs/TopoSortIterative.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import Queue from '../Data-Structures/Queue/Queue'
2+
/**
3+
* @author {RaviSadam}
4+
* @name TopoSortIterative
5+
* @description -
6+
* Topological sorting algorithm implementation in JavaScript(Khan's Algorithm)
7+
* @summary
8+
* Topological sorting for Directed Acyclic Graph is a linear ordering of vertices
9+
* such that for every directed edge u-v, vertex u comes before v in the ordering.
10+
*
11+
* @param graph - Graph (adjacency list)
12+
* @returns {Array} - Gives null if graph has cycle otherwise result array
13+
*
14+
*/
15+
16+
export function TopoSortIterative(graph) {
17+
const n = graph.length
18+
const inDegree = Array(n).fill(0)
19+
const queue = new Queue()
20+
const result = Array(n).fill(0)
21+
let index = 0
22+
23+
for (const neighbors of graph) {
24+
for (const neighbor of neighbors) {
25+
inDegree[neighbor] += 1
26+
}
27+
}
28+
29+
for (let i = 0; i < n; i++) {
30+
if (inDegree[i] === 0) {
31+
queue.enqueue(i)
32+
}
33+
}
34+
while (queue.length !== 0) {
35+
const node = queue.dequeue()
36+
result[index] = node
37+
index += 1
38+
for (let neighbor of graph[node]) {
39+
inDegree[neighbor] -= 1
40+
if (inDegree[neighbor] === 0) {
41+
queue.enqueue(neighbor)
42+
}
43+
}
44+
}
45+
if (index !== n) return null
46+
return result
47+
}

Graphs/TopoSortRecursive.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
function TopoSortRecursiveFunction(graph, visited, stack, path, vertex) {
2+
//marking current vertex as visited
3+
visited.add(vertex)
4+
5+
//marking current vertex as being part of current path
6+
path[vertex] = 1
7+
if (graph[vertex] && graph[vertex].length !== 0) {
8+
for (const neighbor of graph[vertex]) {
9+
//if neighbor is not visited then visit else continue
10+
if (!visited.has(neighbor)) {
11+
TopoSortRecursiveFunction(graph, visited, stack, path, neighbor)
12+
} else if (path[neighbor] == 1) return
13+
}
14+
}
15+
16+
//unmarking vertex
17+
path[vertex] = 0
18+
19+
//visited all vertex coming after the current vertex
20+
//so added to stack
21+
stack.push(vertex)
22+
}
23+
24+
/**
25+
*
26+
* @author {RaviSadam}
27+
* @name TopoSortRecursive
28+
* @description -
29+
* Topological sorting algorithm implementation in JavaScript
30+
* @summary
31+
* Topological sorting for Directed Acyclic Graph is a linear ordering of vertices
32+
* such that for every directed edge u-v, vertex u comes before v in the ordering.
33+
*
34+
* @param graph - Graph (adjacency list)
35+
* @returns {Array} - Gives null if graph has cycle otherwise result array
36+
*
37+
*/
38+
export function TopoSortRecursive(graph) {
39+
const n = graph.length
40+
const stack = []
41+
//visited set for keep tracking of visited vertises
42+
const visited = new Set()
43+
44+
//path array for keep tacking of vertices
45+
//visited in current path
46+
47+
const path = Array(n).fill(0)
48+
for (let i = 0; i < n; i++) {
49+
if (!visited.has(i)) {
50+
TopoSortRecursiveFunction(graph, visited, stack, path, i)
51+
}
52+
}
53+
for (const value of path) {
54+
if (value === 1) return null
55+
}
56+
//reverse the stack for getting exact topological order
57+
stack.reverse()
58+
return stack
59+
}

Graphs/test/TopoSortIterative.test.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { TopoSortIterative } from '../TopoSortIterative'
2+
3+
describe('Iterative Topological Sorting', () => {
4+
test('Graph without cycle', () => {
5+
const graph = [[], [], [3], [1], [0, 1], [0, 2]]
6+
7+
expect(TopoSortIterative(graph, 6)).toEqual([4, 5, 0, 2, 3, 1])
8+
})
9+
test('Graph with cycle', () => {
10+
const graph = [[2], [], [3, 5], [0, 1], [0, 2]]
11+
12+
expect(TopoSortIterative(graph, 6)).toBe(null)
13+
})
14+
})

Graphs/test/TopoSortRecursive.test.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { TopoSortRecursive } from '../TopoSortRecursive'
2+
3+
describe('Recursive Topological Sorting', () => {
4+
test('Graph without cycle', () => {
5+
const graph = [[], [], [3], [1], [0, 1], [0, 2]]
6+
7+
expect(TopoSortRecursive(graph, 6)).toEqual([5, 4, 2, 3, 1, 0])
8+
})
9+
test('Graph with cycle', () => {
10+
const graph = [[2], [], [3, 5], [0, 1], [0, 2]]
11+
12+
expect(TopoSortRecursive(graph, 6)).toBe(null)
13+
})
14+
test('Graph with disconnected components', () => {
15+
const graph = [[1, 2], [3], [3], [], [5], []]
16+
expect(TopoSortRecursive(graph, 6)).toEqual([4, 5, 0, 2, 1, 3])
17+
})
18+
})

0 commit comments

Comments
 (0)