-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
95 lines (80 loc) · 2.63 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
module.exports.solve = solve;
module.exports.addMissingKeys = addMissingKeys;
module.exports.getEdges = getEdges;
module.exports.getInDegree = getInDegree;
// Alternative domain-specific aliases
module.exports.getDependencyLines = getEdges;
module.exports.getDependedBy = getInDegree;
function solve(g) {
let graph = addMissingKeys(g);
let edges = getEdges(graph);
let inDegree = getInDegree(graph);
// Create a queue and enqueue vertices with in-degree of 0
let queue = [];
for(let key in graph) {
if(inDegree[key] == 0) {
queue.push(key);
}
}
// Count of visited vertices to compare against graph's length
// Useful for detecting circular dependency in the graph
let count = 0;
let topOrder = [];
while(queue.length > 0) {
// Extract front of queue and add it to topological order
let u = queue.shift();
topOrder.unshift(u);
// Iterate through dependant nodes of popped node
// and decrease their in-degree by 1
for(let [index, value] of graph[u].entries()) {
inDegree[value]--;
// If in-degree is 0, add it to queue
if(inDegree[value] == 0) {
queue.unshift(value);
}
}
count++;
}
if(count !== Object.keys(graph).length) {
throw new Error('There is a circular dependency in the graph');
} else {
return topOrder;
}
}
function addMissingKeys(graph) {
// Add all the missing keys to the graph as nodes with no in-degrees
for(let key in graph) {
for(let [index, value] of graph[key].entries()) {
if(graph[value] === undefined) {
graph[value] = [];
}
}
}
return graph;
}
function getEdges(graph) {
let edges = [];
for(let key in graph) {
let edge = [];
// If graph node has any in-degrees add the pair to edge list
for(let item of graph[key]) {
if(graph[key].length > 0) {
edges.push([key, item]);
}
}
}
return edges;
}
function getInDegree(graph) {
// Creating a map to store in-degrees of all vertices
let inDegree = {};
for(let key in graph) {
for(let indeg of graph[key]) {
// Traverse the graph and fill in-degrees. Since complete graph has keys
// with no in-degrees, add them as nodes with 0 in-degrees
inDegree[indeg] = inDegree[indeg] === undefined ? 1 : ++inDegree[indeg];
inDegree[key] = inDegree[key] || 0;
}
}
return inDegree;
}