-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathkahns_algorithm.js
102 lines (80 loc) · 2.74 KB
/
kahns_algorithm.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
96
97
98
99
100
101
102
const adjacencyMatrix = [
[0, 0, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
];
const nodes = ["Angela", "Bella", "Ellen", "Jane", "Miranda", "Zoe"];
function hasNodeNoIncomingEdge(adjacencyMatrix, nodeIndex) {
const column = nodeIndex;
for (let row = 0; row < adjacencyMatrix.length; row += 1) {
const cell = adjacencyMatrix[row][column];
if (cell != 0) {
return false;
}
}
return true;
}
function getNodesWithNoIncomingEdge(adjacencyMatrix, nodes) {
return nodes.filter((_, i) => hasNodeNoIncomingEdge(adjacencyMatrix, i));
}
function graphHasEdges(adjacencyMatrix) {
for (let row = 0; row < adjacencyMatrix.length; row += 1) {
for (let column = 0; column < adjacencyMatrix.length; column += 1) {
if (adjacencyMatrix[row][column] == 1) return true;
}
}
return false;
}
function topologicalSort(adjacencyMatrix) {
const L = [];
const S = getNodesWithNoIncomingEdge(adjacencyMatrix, nodes);
while (S.length > 0) {
const node = S.pop();
L.push(node);
const nodeIndex = nodes.indexOf(node);
for (let mIndex = 0; mIndex < nodes.length; mIndex += 1) {
const hasEdgeFromNtoM = adjacencyMatrix[nodeIndex][mIndex];
if (!hasEdgeFromNtoM) continue;
adjacencyMatrix[nodeIndex][mIndex] = 0;
if (hasNodeNoIncomingEdge(adjacencyMatrix, mIndex)) {
const m = nodes[mIndex];
S.push(m);
}
}
}
if (graphHasEdges(adjacencyMatrix)) {
throw new Error("Graph has at least one cycle");
}
return L;
}
function hasMultipleRoots(adjacencyMatrix) {
let countOfRowsWithOnlyZeroes = 0;
for (let row = 0; row < adjacencyMatrix.length; row += 1) {
let rowHasOnlyZeroes = true;
for (let column = 0; column < adjacencyMatrix.length; column += 1) {
if (adjacencyMatrix[row][column] != 0) {
rowHasOnlyZeroes = false;
break;
}
}
if (rowHasOnlyZeroes) countOfRowsWithOnlyZeroes += 1;
}
return countOfRowsWithOnlyZeroes > 1;
}
console.log(hasMultipleRoots(adjacencyMatrix));
const employeesTopologicallySorted = topologicalSort(structuredClone(adjacencyMatrix), nodes);
console.log(employeesTopologicallySorted);
const root = employeesTopologicallySorted[employeesTopologicallySorted.length - 1];
console.log(`INSERT INTO people VALUES("${root}", NULL)`);
for (let i = employeesTopologicallySorted.length - 2; i >= 0; i -= 1) {
const employee = employeesTopologicallySorted[i];
const employeeIndex = nodes.indexOf(employee);
const managerIndex = adjacencyMatrix[employeeIndex].indexOf(1);
const manager = nodes[managerIndex];
console.log(
`INSERT INTO people SELECT "${employee}", rowid FROM people WHERE name = "${manager}" LIMIT 1;`,
);
}