aQute.libg.tarjan.Tarjan Maven / Gradle / Ivy
The newest version!
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.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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 Set> scc = new HashSet<>();
private Node root = new Node(null);
// public ArrayList> tarjan(Node v, AdjacencyList list){
// v.index = index;
// v.lowlink = index;
// index++;
// stack.add(0, v);
// for(Edge e : list.getAdjacent(v)){
// Node n = e.to;
// if(n.index == -1){
// tarjan(n, list);
// v.lowlink = Math.min(v.lowlink, n.lowlink);
// }else if(stack.contains(n)){
// v.lowlink = Math.min(v.lowlink, n.index);
// }
// }
// if(v.lowlink == v.index){
// Node n;
// ArrayList component = new ArrayList();
// do{
// n = stack.remove(0);
// component.add(n);
// }while(n != v);
// SCC.add(component);
// }
// return SCC;
// }
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) {
Set component = new HashSet<>();
Node n;
do {
n = stack.remove(0);
component.add(n.name);
} while (n != v);
scc.add(component);
}
}
Set> 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);
}
}