-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Added Kann's algorithm #1676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Kann's algorithm #1676
Changes from 1 commit
74e8ec2
9f3aa64
2f2c099
3e9c9e4
f0325a5
99535c5
35fe1c3
ef63f66
154a330
191993f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
* | ||
*/ | ||
|
||
export function kannsAlgorithm(graph, n) { | ||
if (n === null || n === undefined) throw Error('Invalid n was given') | ||
const inorder = Array(n).fill(0) | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
const result = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (By the way, you could preallocate this array.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preallocate could increase the time complexity. At the end we need to check array filled or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No, not really. It's still linear time in the size of the graph - O(n + m) where n is the number of nodes and m is the number of edges. (Allocation can also optimistically be assumed to be constant time.)
Yes, and that can be done in constant time, if you keep an index to the last element. It'd look something like this: const topoOrder = Array(n) // preallocate
const idx = 0
...
// to push:
topoOrder[idx++] = node
...
if (idx < n) return null; // cyclic Or another variant to write this would be: const topoOrder = Array(n) // preallocate
for (let i = 0; i < n; ++i) {
if (stack.length === 0) return null; // cyclic
const node = stack.pop();
topoOrder[i] = node;
...
} The benefit is that when a topological order exists (which should usually be the case; this is the "happy path"), you can save some reallocations of the array. But this is just a suggestion, I'm fine with pushing to keep the code simple as well. Though perhaps the preallocation variant is a bit more readable, since it makes explicit that we want to have all n nodes be in this array. |
||
for (let entry of graph) { | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
for (let edge of entry) { | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
inorder[edge] += 1 | ||
} | ||
} | ||
const queue = [] | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
console.log(inorder) | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
for (let i = 0; i < n; i++) { | ||
if (inorder[i] === 0) { | ||
queue.push(i) | ||
} | ||
} | ||
while (queue.length != 0) { | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
const node = queue[0] | ||
result.push(node) | ||
queue.splice(0, 1) | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
for (let nei of graph[node]) { | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
inorder[nei] -= 1 | ||
if (inorder[nei] == 0) { | ||
This conversation was marked as resolved.
Show resolved
Hide resolved
|
||
queue.push(nei) | ||
} | ||
} | ||
} | ||
if (result.length != n) return [] | ||
return result | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { kannsAlgorithm } from '../KannsAlgorithm' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You forgot to delete this file. |
||
|
||
appgurueu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
test('Test Case 1: Graph without cycle', () => { | ||
appgurueu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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', () => { | ||
appgurueu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const graph = [[2], [], [3, 5], [0, 1], [0, 2]] | ||
|
||
expect(kannsAlgorithm(graph, 6)).toEqual([]) | ||
}) |
Uh oh!
There was an error while loading. Please reload this page.