package graph; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.Stack; // parcours en profondeur public class DFS<V> { private final Graph<V> g; private final HashMap<V, Integer> visited; private int count; public DFS(Graph<V> g) { this.g = g; this.visited = new HashMap<V, Integer>(); this.count = 0; } public void dfs(V v) { if (this.visited.containsKey(v)) return; this.visited.put(v, this.count++); for (V w : this.g.successors(v)) dfs(w); } public void dfs() { for (V v : this.g.vertices()) dfs(v); } public boolean visited(V v) { return this.visited.containsKey(v); } public int getNum(V v) { return this.visited.get(v); } } class DFSset<V> { private final Graph<V> g; private final HashSet<V> visited; DFSset(Graph<V> g) { this.g = g; this.visited = new HashSet<V>(); } void dfs(V v) { if (this.visited.contains(v)) return; this.visited.add(v); for (V w : this.g.successors(v)) dfs(w); } void dfs() { for (V v : this.g.vertices()) dfs(v); } boolean existsPath(V u, V v) { this.visited.clear(); dfs(u); return this.visited.contains(v); } // test de connexité (pour un graphe non orienté) boolean isConnected() { Set<V> vs = this.g.vertices(); if (vs.isEmpty()) return true; V v0 = vs.iterator().next(); // un sommet quelconque this.visited.clear(); dfs(v0); for (V v: vs) if (!this.visited.contains(v)) return false; return true; } } // avec une pile explicite, pour éviter StackOverflow class DFSStack<V> { private final Graph<V> g; private final HashMap<V, Integer> visited; private int count; DFSStack(Graph<V> g) { this.g = g; this.visited = new HashMap<V, Integer>(); this.count = 0; } void dfs(V v) { Stack<V> stack = new Stack<V>(); stack.push(v); while (!stack.isEmpty()) { v = stack.pop(); if (this.visited.containsKey(v)) continue; this.visited.put(v, this.count++); for (V w : this.g.successors(v)) stack.push(w); } } void dfs() { for (V v : this.g.vertices()) dfs(v); } boolean visited(V v) { return this.visited.containsKey(v); } int getNum(V v) { return this.visited.get(v); } } class CycleDetection<V> { enum Color { White, Gray, Black}; private final Graph<V> g; private final HashMap<V, Color> color; public CycleDetection(Graph<V> g) { this.g = g; this.color = new HashMap<V, Color>(); } boolean dfs(V v) { if (this.color.get(v) == Color.Gray) return true; if (this.color.get(v) == Color.Black) return false; this.color.put(v, Color.Gray); for (V w : this.g.successors(v)) if (dfs(w)) return true; this.color.put(v, Color.Black); return false; } boolean hasCycle() { for (V v : this.g.vertices()) color.put(v, Color.White); for (V v : this.g.vertices()) if (dfs(v)) return true; return false; } } class TestDFS { public static void main(String[] args) { Graph<Integer> g = new Graph<Integer>(); /* 1 -> 2 3 * | /^| / | * V / V V V * 4 <- 5 6) */ for (int i = 1; i <= 6; i++) g.addVertex(i); g.addEdge(1, 2); g.addEdge(1, 4); g.addEdge(2, 5); g.addEdge(3, 5); g.addEdge(3, 6); g.addEdge(4, 2); g.addEdge(5, 4); g.addEdge(6, 6); DFS<Integer> dfs = new DFS<Integer>(g); dfs.dfs(); for (int v : g.vertices()) System.out.println("dfs(" + v + ")=" + dfs.getNum(v)); //System.out.println(dfs.getNum(7)); System.out.println("---"); DFSStack<Integer> dfss = new DFSStack<>(g); dfss.dfs(); for (int v : g.vertices()) System.out.println("dfs(" + v + ")=" + dfss.getNum(v)); System.out.println("---"); CycleDetection<Integer> cd = new CycleDetection<>(g); System.out.println(cd.hasCycle()); Graph<Integer> gr = Graph.grid(3, 3, false); dfss = new DFSStack<>(gr); dfss.dfs(0); for (int v = 0; v < 9; v++) { System.out.print(v + "(" + dfss.getNum(v) + ") "); if (v % 3 == 2) System.out.println(); } System.out.println("Test DFS"); } }