blob: 71b8eb11c77a40f1279db5e88308d97f1a711d1b [file] [log] [blame]
package org.testng.internal;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* Implementation of the Tarjan algorithm to find and display a cycle in a graph.
* @author cbeust
*/
public class Tarjan<T> {
int m_index = 0;
private Stack<T> m_s;
Map<T, Integer> m_indices = Maps.newHashMap();
Map<T, Integer> m_lowlinks = Maps.newHashMap();
private List<T> m_cycle;
public Tarjan(Graph<T> graph, T start) {
m_s = new Stack<T>();
run(graph, start);
}
private void run(Graph<T> graph, T v) {
m_indices.put(v, m_index);
m_lowlinks.put(v, m_index);
m_index++;
m_s.push(v);
for (T vprime : graph.getPredecessors(v)) {
if (! m_indices.containsKey(vprime)) {
run(graph, vprime);
int min = Math.min(m_lowlinks.get(v), m_lowlinks.get(vprime));
m_lowlinks.put(v, min);
}
else if (m_s.contains(vprime)) {
m_lowlinks.put(v, Math.min(m_lowlinks.get(v), m_indices.get(vprime)));
}
}
if (m_lowlinks.get(v) == m_indices.get(v)) {
m_cycle = Lists.newArrayList();
T n;
do {
n = m_s.pop();
m_cycle.add(n);
} while (! n.equals(v));
}
}
public static void main(String[] args) {
Graph<String> g = new Graph<String>();
g.addNode("a");
g.addNode("b");
g.addNode("c");
g.addNode("d");
String[] edges = new String[] {
"a", "b",
"b", "a",
"c", "d",
"d", "a",
"a", "c",
};
for (int i = 0; i < edges.length; i += 2) {
g.addPredecessor(edges[i], edges[i+1]);
}
new Tarjan<String>(g, "a");
}
public List<T> getCycle() {
return m_cycle;
}
}