programming-examples/js/Algorithms/tarjan-connected-components.js
2019-11-15 12:59:38 +01:00

76 lines
2.1 KiB
JavaScript

(function (exports) {
'use strict';
/**
* Tarjan's algorithm for finding the connected components in a graph.<br><br>
* Time complexity: O(|E| + |V|) where E is a number of edges and |V|
* is the number of nodes.
*
* @public
* @module graphs/others/tarjan-connected-components
* @param {Array} graph Adjacency list, which represents the graph.
* @returns {Array} Connected components.
*
* @example
* var tarjanConnectedComponents =
* require('path-to-algorithms/src/graphs/' +
* 'others/tarjan-connected-components').tarjanConnectedComponents;
* var graph = {
* v1: ['v2', 'v5'],
* v2: [],
* v3: ['v1', 'v2', 'v4', 'v5'],
* v4: [],
* v5: []
* };
* var vertices = topsort(graph); // ['v3', 'v4', 'v1', 'v5', 'v2']
*/
function tarjanConnectedComponents(graph) {
graph = graph || {};
const indexes = {};
const lowIndexes = {};
const onStack = {};
const result = [];
const stack = [];
var index = 1;
const connectedComponent = function (node) {
stack.push(node);
onStack[node] = true;
indexes[node] = index;
lowIndexes[node] = index;
index += 1;
graph[node].forEach(function (n) {
if (indexes[n] === undefined) {
connectedComponent(n);
lowIndexes[node] = Math.min(lowIndexes[n], lowIndexes[node]);
} else if (onStack[n]) {
lowIndexes[node] = Math.min(lowIndexes[node], indexes[n]);
}
});
// This is a "root" node
const cc = [];
if (indexes[node] === lowIndexes[node]) {
var current;
do {
current = stack.pop();
onStack[current] = false;
cc.push(current);
} while (stack.length > 0 && node !== current);
result.push(cc);
}
};
Object.keys(graph)
.forEach(function (n) {
if (!indexes[n]) {
connectedComponent(n);
}
});
return result;
}
exports.tarjanConnectedComponents = tarjanConnectedComponents;
}(typeof exports === 'undefined' ? window : exports));