blob: 063006e840a3478fd064fc123415b979fd836fe2 [file] [log] [blame]
Stuart McCulloch26e7a5a2011-10-17 10:31:43 +00001package aQute.libg.tarjan;
2
3import static java.lang.Math.*;
4
5import java.util.*;
6
7public class Tarjan<T> {
8
9 public class Node {
10 final T name;
11 final List<Node> adjacent = new ArrayList<Node>();
12 int low = -1;
13 int index = -1;
14
15 public Node(T name) {
16 this.name = name;
17 }
18
19 public String toString() {
20 return name + "{" + index + "," + low + "}";
21 }
22 }
23
24 private int index = 0;
25 private List<Node> stack = new ArrayList<Node>();
26 private Set<Set<T>> scc = new HashSet<Set<T>>();
27 private Node root = new Node(null);
28
29
30// public ArrayList<ArrayList<Node>> tarjan(Node v, AdjacencyList list){
31// v.index = index;
32// v.lowlink = index;
33// index++;
34// stack.add(0, v);
35// for(Edge e : list.getAdjacent(v)){
36// Node n = e.to;
37// if(n.index == -1){
38// tarjan(n, list);
39// v.lowlink = Math.min(v.lowlink, n.lowlink);
40// }else if(stack.contains(n)){
41// v.lowlink = Math.min(v.lowlink, n.index);
42// }
43// }
44// if(v.lowlink == v.index){
45// Node n;
46// ArrayList<Node> component = new ArrayList<Node>();
47// do{
48// n = stack.remove(0);
49// component.add(n);
50// }while(n != v);
51// SCC.add(component);
52// }
53// return SCC;
54// }
55
56 void tarjan(Node v) {
57 v.index = index;
58 v.low = index;
59 index++;
60 stack.add(0, v);
61 for (Node n : v.adjacent) {
62 if (n.index == -1) {
63 // first time visit
64 tarjan(n);
65 v.low = min(v.low, n.low);
66 } else if (stack.contains(n)) {
67 v.low = min(v.low, n.index);
68 }
69 }
70
71 if (v!=root && v.low == v.index) {
72 Set<T> component = new HashSet<T>();
73 Node n;
74 do {
75 n = stack.remove(0);
76 component.add(n.name);
77 } while (n != v);
78 scc.add(component);
79 }
80 }
81
82 Set<Set<T>> getResult(Map<T, ? extends Collection<T>> graph) {
83 Map<T, Node> index = new HashMap<T, Node>();
84
85 for (Map.Entry<T, ? extends Collection<T>> entry : graph.entrySet()) {
86 Node node = getNode(index, entry.getKey());
87 root.adjacent.add(node);
88 for (T adj : entry.getValue())
89 node.adjacent.add(getNode(index, adj));
90 }
91 tarjan(root);
92 return scc;
93 }
94
95 private Node getNode(Map<T, Node> index, T key) {
96 Node node = index.get(key);
97 if (node == null) {
98 node = new Node(key);
99 index.put(key, node);
100 }
101 return node;
102 }
103
104 public static <T> Set<Set<T>> tarjan(Map<T, Set<T>> graph) {
105 Tarjan<T> tarjan = new Tarjan<T>();
106 return tarjan.getResult(graph);
107 }
108}