aQute.libg.tarjan.Tarjan Maven / Gradle / Ivy
package aQute.libg.tarjan;
import static java.lang.Math.min;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Tarjan {
public class Node {
final T name;
final List adjacent = new ArrayList<>();
int low = -1;
int index = -1;
public Node(T name) {
this.name = name;
}
@Override
public String toString() {
return name + "{" + index + "," + low + "}";
}
}
private int index = 0;
private List stack = new ArrayList<>();
private List> scc = new ArrayList<>();
private Node root = new Node(null);
void tarjan(Node v) {
v.index = index;
v.low = index;
index++;
stack.add(0, v);
for (Node n : v.adjacent) {
if (n.index == -1) {
// first time visit
tarjan(n);
v.low = min(v.low, n.low);
} else if (stack.contains(n)) {
v.low = min(v.low, n.index);
}
}
if (v != root && v.low == v.index) {
List component = new ArrayList<>();
Node n;
do {
n = stack.remove(0);
component.add(n.name);
} while (n != v);
scc.add(component);
}
}
List> getResult(Map> graph) {
Map index = new HashMap<>();
for (Map.Entry> entry : graph.entrySet()) {
Node node = getNode(index, entry.getKey());
root.adjacent.add(node);
for (T adj : entry.getValue())
node.adjacent.add(getNode(index, adj));
}
tarjan(root);
return scc;
}
private Node getNode(Map index, T key) {
Node node = index.get(key);
if (node == null) {
node = new Node(key);
index.put(key, node);
}
return node;
}
public static Collection extends Collection> tarjan(Map> graph) {
Tarjan tarjan = new Tarjan<>();
return tarjan.getResult(graph);
}
}