cytoscape
Version:
Graph theory (a.k.a. network) library for analysis and visualisation
76 lines (65 loc) • 1.94 kB
JavaScript
let tarjanStronglyConnected = function() {
let eles = this;
let nodes = {};
let index = 0;
let components = [];
let stack = [];
let cut = eles.spawn(eles);
const stronglyConnectedSearch = sourceNodeId => {
stack.push(sourceNodeId);
nodes[sourceNodeId] = {
index : index,
low : index++,
explored : false
};
let connectedEdges = eles.getElementById(sourceNodeId)
.connectedEdges()
.intersection(eles);
connectedEdges.forEach(edge => {
let targetNodeId = edge.target().id();
if (targetNodeId !== sourceNodeId) {
if (!(targetNodeId in nodes)) {
stronglyConnectedSearch(targetNodeId);
}
if (!(nodes[targetNodeId].explored)) {
nodes[sourceNodeId].low = Math.min(nodes[sourceNodeId].low,
nodes[targetNodeId].low);
}
}
});
if (nodes[sourceNodeId].index === nodes[sourceNodeId].low) {
let componentNodes = eles.spawn();
for (;;) {
const nodeId = stack.pop();
componentNodes.merge(eles.getElementById(nodeId));
nodes[nodeId].low = nodes[sourceNodeId].index;
nodes[nodeId].explored = true;
if (nodeId === sourceNodeId) {
break;
}
}
let componentEdges = componentNodes.edgesWith(componentNodes);
let component = componentNodes.merge(componentEdges);
components.push(component);
cut = cut.difference(component);
}
};
eles.forEach(ele => {
if (ele.isNode()) {
let nodeId = ele.id();
if (!(nodeId in nodes)) {
stronglyConnectedSearch(nodeId);
}
}
});
return {
cut,
components
};
};
export default {
tarjanStronglyConnected,
tsc: tarjanStronglyConnected,
tscc: tarjanStronglyConnected,
tarjanStronglyConnectedComponents: tarjanStronglyConnected
};