From 74e8ec235f790f9dec9a16b9e787da56ee576576 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 8 Jul 2024 04:26:25 +0000 Subject: [PATCH 1/8] feat:added kanns algorithm --- Graphs/KannsAlgorithm.js | 44 ++++++++++++++++++++++++++++++ Graphs/test/KannsAlgorithm.test.js | 13 +++++++++ 2 files changed, 57 insertions(+) create mode 100644 Graphs/KannsAlgorithm.js create mode 100644 Graphs/test/KannsAlgorithm.test.js diff --git a/Graphs/KannsAlgorithm.js b/Graphs/KannsAlgorithm.js new file mode 100644 index 0000000000..1b9cb43540 --- /dev/null +++ b/Graphs/KannsAlgorithm.js @@ -0,0 +1,44 @@ +/** + * @author {RaviSadam} + * @name kannsAlgorithm + * @description - + * Kann's Algorithm implementation in JavaScript + * @summary + * Kann's Algorithm is used for topological sorting in directed acyclic graphs + * + * @param graph - Graph [[v1,v2],[v3,v4,v5]..] + * @param n - number of vertices + * @returns {Array} - Empty array if cycle is detected or else result array; + * + */ + +export function kannsAlgorithm(graph, n) { + if (n === null || n === undefined) throw Error('Invalid n was given') + const inorder = Array(n).fill(0) + const result = [] + for (let entry of graph) { + for (let edge of entry) { + inorder[edge] += 1 + } + } + const queue = [] + console.log(inorder) + for (let i = 0; i < n; i++) { + if (inorder[i] === 0) { + queue.push(i) + } + } + while (queue.length != 0) { + const node = queue[0] + result.push(node) + queue.splice(0, 1) + for (let nei of graph[node]) { + inorder[nei] -= 1 + if (inorder[nei] == 0) { + queue.push(nei) + } + } + } + if (result.length != n) return [] + return result +} diff --git a/Graphs/test/KannsAlgorithm.test.js b/Graphs/test/KannsAlgorithm.test.js new file mode 100644 index 0000000000..3c00495b78 --- /dev/null +++ b/Graphs/test/KannsAlgorithm.test.js @@ -0,0 +1,13 @@ +import { kannsAlgorithm } from '../KannsAlgorithm' + +test('Test Case 1: Graph without cycle', () => { + const graph = [[], [], [3], [1], [0, 1], [0, 2]] + + expect(kannsAlgorithm(graph, 6)).toEqual([4, 5, 0, 2, 3, 1]) +}) + +test('Test Case 2: Graph with cycle', () => { + const graph = [[2], [], [3, 5], [0, 1], [0, 2]] + + expect(kannsAlgorithm(graph, 6)).toEqual([]) +}) From 9f3aa64da649ef18acc1a1c20dec528076a02489 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 11 Jul 2024 05:09:03 +0000 Subject: [PATCH 2/8] Updated kahn's algorithm --- Graphs/KahnsAlgorithm.js | 45 ++++++++++++++++++++++++++++++ Graphs/test/KahnsAlgorithm.test.js | 13 +++++++++ 2 files changed, 58 insertions(+) create mode 100644 Graphs/KahnsAlgorithm.js create mode 100644 Graphs/test/KahnsAlgorithm.test.js diff --git a/Graphs/KahnsAlgorithm.js b/Graphs/KahnsAlgorithm.js new file mode 100644 index 0000000000..78fe371c4d --- /dev/null +++ b/Graphs/KahnsAlgorithm.js @@ -0,0 +1,45 @@ +import Queue from '../Data-Structures/Queue/Queue' + +/** + * @author {RaviSadam} + * @name KahnsAlgorithm + * @description - + * Kahn's Algorithm implementation in JavaScript + * @summary + * Kahn's Algorithm is used for finding the topological sorting order of directed acyclic graph + * + * @param graph - Graph (adjacency list) + * @param n - Size of graph + * @returns {Array} - null if cycle is detected or else result array + * + */ + +export function KahnsAlgorithm(graph, n) { + if (n === null || n === undefined) throw Error('Invalid n was given') + const inDegree = Array(n).fill(0) + const result = [] + for (const neigbhours of graph) { + for (const neigbhour of neigbhours) { + inDegree[neigbhour] += 1 + } + } + const queue = new Queue() + + for (let i = 0; i < n; i++) { + if (inDegree[i] === 0) { + queue.enqueue(i) + } + } + while (queue.length !== 0) { + const node = queue.dequeue() + result.push(node) + for (const neigbhour of graph[node]) { + inDegree[neigbhour] -= 1 + if (inDegree[neigbhour] == 0) { + queue.enqueue(neigbhour) + } + } + } + if (result.length !== n) return null + return result +} diff --git a/Graphs/test/KahnsAlgorithm.test.js b/Graphs/test/KahnsAlgorithm.test.js new file mode 100644 index 0000000000..799cb840ce --- /dev/null +++ b/Graphs/test/KahnsAlgorithm.test.js @@ -0,0 +1,13 @@ +import { KahnsAlgorithm } from '../KahnsAlgorithm' + +test('Graph without cycle', () => { + const graph = [[], [], [3], [1], [0, 1], [0, 2]] + + expect(KahnsAlgorithm(graph, 6)).toEqual([4, 5, 0, 2, 3, 1]) +}) + +test('Graph with cycle', () => { + const graph = [[2], [], [3, 5], [0, 1], [0, 2]] + + expect(KahnsAlgorithm(graph, 6)).toBe(null) +}) From 2f2c099b9da6012aeb44f0119bfd40e20b64bb01 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 11 Jul 2024 05:16:45 +0000 Subject: [PATCH 3/8] Updated kahn's algorithm --- Graphs/KahnsAlgorithm.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Graphs/KahnsAlgorithm.js b/Graphs/KahnsAlgorithm.js index 78fe371c4d..a13ec7040e 100644 --- a/Graphs/KahnsAlgorithm.js +++ b/Graphs/KahnsAlgorithm.js @@ -18,9 +18,9 @@ export function KahnsAlgorithm(graph, n) { if (n === null || n === undefined) throw Error('Invalid n was given') const inDegree = Array(n).fill(0) const result = [] - for (const neigbhours of graph) { - for (const neigbhour of neigbhours) { - inDegree[neigbhour] += 1 + for (const neighbours of graph) { + for (const neighbour of neighbours) { + inDegree[neighbour] += 1 } } const queue = new Queue() @@ -33,10 +33,10 @@ export function KahnsAlgorithm(graph, n) { while (queue.length !== 0) { const node = queue.dequeue() result.push(node) - for (const neigbhour of graph[node]) { - inDegree[neigbhour] -= 1 - if (inDegree[neigbhour] == 0) { - queue.enqueue(neigbhour) + for (const neighbour of graph[node]) { + inDegree[neighbour] -= 1 + if (inDegree[neighbour] == 0) { + queue.enqueue(neighbour) } } } From 3e9c9e431979c1b4daccd2165a75839fd23ad22b Mon Sep 17 00:00:00 2001 From: "sadamravi7@gmail.com" Date: Thu, 11 Jul 2024 23:43:02 +0530 Subject: [PATCH 4/8] feat: added topological sorting algorithm --- Graphs/TopoSortIterative.js | 47 +++++++++++++++++++++ Graphs/TopoSortRecursive.js | 59 +++++++++++++++++++++++++++ Graphs/test/TopoSortIterative.test.js | 14 +++++++ Graphs/test/TopoSortRecursive.test.js | 18 ++++++++ 4 files changed, 138 insertions(+) create mode 100644 Graphs/TopoSortIterative.js create mode 100644 Graphs/TopoSortRecursive.js create mode 100644 Graphs/test/TopoSortIterative.test.js create mode 100644 Graphs/test/TopoSortRecursive.test.js diff --git a/Graphs/TopoSortIterative.js b/Graphs/TopoSortIterative.js new file mode 100644 index 0000000000..1501009a86 --- /dev/null +++ b/Graphs/TopoSortIterative.js @@ -0,0 +1,47 @@ +import Queue from '../Data-Structures/Queue/Queue' +/** + * @author {RaviSadam} + * @name TopoSortIterative + * @description - + * Topological sorting algorithm implementation in JavaScript(Khan's Algorithm) + * @summary + * Topological sorting for Directed Acyclic Graph is a linear ordering of vertices + * such that for every directed edge u-v, vertex u comes before v in the ordering. + * + * @param graph - Graph (adjacency list) + * @returns {Array} - Gives null if graph has cycle otherwise result array + * + */ + +export function TopoSortIterative(graph) { + const n = graph.length + const inDegree = Array(n).fill(0) + const queue = new Queue() + const result = Array(n).fill(0) + let index = 0 + + for (const neighbors of graph) { + for (const neighbor of neighbors) { + inDegree[neighbor] += 1 + } + } + + for (let i = 0; i < n; i++) { + if (inDegree[i] === 0) { + queue.enqueue(i) + } + } + while (queue.length !== 0) { + const node = queue.dequeue() + result[index] = node + index += 1 + for (let neighbor of graph[node]) { + inDegree[neighbor] -= 1 + if (inDegree[neighbor] === 0) { + queue.enqueue(neighbor) + } + } + } + if (index !== n) return null + return result +} diff --git a/Graphs/TopoSortRecursive.js b/Graphs/TopoSortRecursive.js new file mode 100644 index 0000000000..1d77543b74 --- /dev/null +++ b/Graphs/TopoSortRecursive.js @@ -0,0 +1,59 @@ +function TopoSortRecursiveFunction(graph, visited, stack, path, vertex) { + //marking current vertex as visited + visited.add(vertex) + + //marking current vertex as being part of current path + path[vertex] = 1 + if (graph[vertex] && graph[vertex].length !== 0) { + for (const neighbor of graph[vertex]) { + //if neighbor is not visited then visit else continue + if (!visited.has(neighbor)) { + TopoSortRecursiveFunction(graph, visited, stack, path, neighbor) + } else if (path[neighbor] == 1) return + } + } + + //unmarking vertex + path[vertex] = 0 + + //visited all vertex coming after the current vertex + //so added to stack + stack.push(vertex) +} + +/** + * + * @author {RaviSadam} + * @name TopoSortRecursive + * @description - + * Topological sorting algorithm implementation in JavaScript + * @summary + * Topological sorting for Directed Acyclic Graph is a linear ordering of vertices + * such that for every directed edge u-v, vertex u comes before v in the ordering. + * + * @param graph - Graph (adjacency list) + * @returns {Array} - Gives null if graph has cycle otherwise result array + * + */ +export function TopoSortRecursive(graph) { + const n = graph.length + const stack = [] + //visited set for keep tracking of visited vertises + const visited = new Set() + + //path array for keep tacking of vertices + //visited in current path + + const path = Array(n).fill(0) + for (let i = 0; i < n; i++) { + if (!visited.has(i)) { + TopoSortRecursiveFunction(graph, visited, stack, path, i) + } + } + for (const value of path) { + if (value === 1) return null + } + //reverse the stack for getting exact topological order + stack.reverse() + return stack +} diff --git a/Graphs/test/TopoSortIterative.test.js b/Graphs/test/TopoSortIterative.test.js new file mode 100644 index 0000000000..b029580c84 --- /dev/null +++ b/Graphs/test/TopoSortIterative.test.js @@ -0,0 +1,14 @@ +import { TopoSortIterative } from '../TopoSortIterative' + +describe('Iterative Topological Sorting', () => { + test('Graph without cycle', () => { + const graph = [[], [], [3], [1], [0, 1], [0, 2]] + + expect(TopoSortIterative(graph, 6)).toEqual([4, 5, 0, 2, 3, 1]) + }) + test('Graph with cycle', () => { + const graph = [[2], [], [3, 5], [0, 1], [0, 2]] + + expect(TopoSortIterative(graph, 6)).toBe(null) + }) +}) diff --git a/Graphs/test/TopoSortRecursive.test.js b/Graphs/test/TopoSortRecursive.test.js new file mode 100644 index 0000000000..6f94f32368 --- /dev/null +++ b/Graphs/test/TopoSortRecursive.test.js @@ -0,0 +1,18 @@ +import { TopoSortRecursive } from '../TopoSortRecursive' + +describe('Recursive Topological Sorting', () => { + test('Graph without cycle', () => { + const graph = [[], [], [3], [1], [0, 1], [0, 2]] + + expect(TopoSortRecursive(graph, 6)).toEqual([5, 4, 2, 3, 1, 0]) + }) + test('Graph with cycle', () => { + const graph = [[2], [], [3, 5], [0, 1], [0, 2]] + + expect(TopoSortRecursive(graph, 6)).toBe(null) + }) + test('Graph with disconnected components', () => { + const graph = [[1, 2], [3], [3], [], [5], []] + expect(TopoSortRecursive(graph, 6)).toEqual([4, 5, 0, 2, 1, 3]) + }) +}) From 99535c5e8bd527c2bff5dab2e7376e576ffc2f97 Mon Sep 17 00:00:00 2001 From: Ravi Sadam <108484600+RaviSadam@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:53:07 +0530 Subject: [PATCH 5/8] Delete Graphs/KahnsAlgorithm.js Deleted KahnaAlgorithm.js --- Graphs/KahnsAlgorithm.js | 45 ---------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 Graphs/KahnsAlgorithm.js diff --git a/Graphs/KahnsAlgorithm.js b/Graphs/KahnsAlgorithm.js deleted file mode 100644 index a13ec7040e..0000000000 --- a/Graphs/KahnsAlgorithm.js +++ /dev/null @@ -1,45 +0,0 @@ -import Queue from '../Data-Structures/Queue/Queue' - -/** - * @author {RaviSadam} - * @name KahnsAlgorithm - * @description - - * Kahn's Algorithm implementation in JavaScript - * @summary - * Kahn's Algorithm is used for finding the topological sorting order of directed acyclic graph - * - * @param graph - Graph (adjacency list) - * @param n - Size of graph - * @returns {Array} - null if cycle is detected or else result array - * - */ - -export function KahnsAlgorithm(graph, n) { - if (n === null || n === undefined) throw Error('Invalid n was given') - const inDegree = Array(n).fill(0) - const result = [] - for (const neighbours of graph) { - for (const neighbour of neighbours) { - inDegree[neighbour] += 1 - } - } - const queue = new Queue() - - for (let i = 0; i < n; i++) { - if (inDegree[i] === 0) { - queue.enqueue(i) - } - } - while (queue.length !== 0) { - const node = queue.dequeue() - result.push(node) - for (const neighbour of graph[node]) { - inDegree[neighbour] -= 1 - if (inDegree[neighbour] == 0) { - queue.enqueue(neighbour) - } - } - } - if (result.length !== n) return null - return result -} From 35fe1c354a8d330d076379e32d1283e453251099 Mon Sep 17 00:00:00 2001 From: Ravi Sadam <108484600+RaviSadam@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:53:30 +0530 Subject: [PATCH 6/8] Delete Graphs/KannsAlgorithm.js Deleted Graphs/KannsAlgorithm.js --- Graphs/KannsAlgorithm.js | 44 ---------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 Graphs/KannsAlgorithm.js diff --git a/Graphs/KannsAlgorithm.js b/Graphs/KannsAlgorithm.js deleted file mode 100644 index 1b9cb43540..0000000000 --- a/Graphs/KannsAlgorithm.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @author {RaviSadam} - * @name kannsAlgorithm - * @description - - * Kann's Algorithm implementation in JavaScript - * @summary - * Kann's Algorithm is used for topological sorting in directed acyclic graphs - * - * @param graph - Graph [[v1,v2],[v3,v4,v5]..] - * @param n - number of vertices - * @returns {Array} - Empty array if cycle is detected or else result array; - * - */ - -export function kannsAlgorithm(graph, n) { - if (n === null || n === undefined) throw Error('Invalid n was given') - const inorder = Array(n).fill(0) - const result = [] - for (let entry of graph) { - for (let edge of entry) { - inorder[edge] += 1 - } - } - const queue = [] - console.log(inorder) - for (let i = 0; i < n; i++) { - if (inorder[i] === 0) { - queue.push(i) - } - } - while (queue.length != 0) { - const node = queue[0] - result.push(node) - queue.splice(0, 1) - for (let nei of graph[node]) { - inorder[nei] -= 1 - if (inorder[nei] == 0) { - queue.push(nei) - } - } - } - if (result.length != n) return [] - return result -} From ef63f6685b46dbb29698ccf7677b0376699b043f Mon Sep 17 00:00:00 2001 From: Ravi Sadam <108484600+RaviSadam@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:54:50 +0530 Subject: [PATCH 7/8] Delete Graphs/test/KahnsAlgorithm.test.js Graphs/test/KahnsAlgorithm.test.js --- Graphs/test/KahnsAlgorithm.test.js | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 Graphs/test/KahnsAlgorithm.test.js diff --git a/Graphs/test/KahnsAlgorithm.test.js b/Graphs/test/KahnsAlgorithm.test.js deleted file mode 100644 index 799cb840ce..0000000000 --- a/Graphs/test/KahnsAlgorithm.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { KahnsAlgorithm } from '../KahnsAlgorithm' - -test('Graph without cycle', () => { - const graph = [[], [], [3], [1], [0, 1], [0, 2]] - - expect(KahnsAlgorithm(graph, 6)).toEqual([4, 5, 0, 2, 3, 1]) -}) - -test('Graph with cycle', () => { - const graph = [[2], [], [3, 5], [0, 1], [0, 2]] - - expect(KahnsAlgorithm(graph, 6)).toBe(null) -}) From 154a33024a5efed94f6643a853bbec5ac09a3d6c Mon Sep 17 00:00:00 2001 From: Ravi Sadam <108484600+RaviSadam@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:56:29 +0530 Subject: [PATCH 8/8] Delete Graphs/test/KannsAlgorithm.test.js --- Graphs/test/KannsAlgorithm.test.js | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 Graphs/test/KannsAlgorithm.test.js diff --git a/Graphs/test/KannsAlgorithm.test.js b/Graphs/test/KannsAlgorithm.test.js deleted file mode 100644 index 3c00495b78..0000000000 --- a/Graphs/test/KannsAlgorithm.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { kannsAlgorithm } from '../KannsAlgorithm' - -test('Test Case 1: Graph without cycle', () => { - const graph = [[], [], [3], [1], [0, 1], [0, 2]] - - expect(kannsAlgorithm(graph, 6)).toEqual([4, 5, 0, 2, 3, 1]) -}) - -test('Test Case 2: Graph with cycle', () => { - const graph = [[2], [], [3, 5], [0, 1], [0, 2]] - - expect(kannsAlgorithm(graph, 6)).toEqual([]) -})