▶ 书中第四章部分程序,加上自己补充的代码,图的深度优先遍历
● 无向图的深度优先遍历,有向 / 无向图代码仅若干方法名不同,包括递归和非递归版本,去掉了顶点有效性的检查
1 package package01; 2 3 import java.util.Iterator; // nonRecursiveDFS 需要 4 import edu.princeton.cs.algs4.In; 5 import edu.princeton.cs.algs4.StdOut; 6 import edu.princeton.cs.algs4.Graph; 7 import edu.princeton.cs.algs4.Stack; // recursiveDFS 不用 8 9 public class class01 10 { 11 private final int s; // 根顶点,depthFirstPath 需要 12 private boolean[] marked; // 顶点是否已被遍历 13 private int count; // 已遍历的顶点数(含后退),即从 s 可达的顶点数,depthFirstPath 不用 14 private int[] edgeTo; // 每个顶点在 s - v 路径中的父顶点,depthFirstPath 需要 15 16 public class01(Graph G, int inputS) // 初始化,开始DFS 17 { 18 s = inputS; 19 marked = new boolean[G.V()]; 20 edgeTo = new int[G.V()]; 21 recursiveDFS(G, s); 22 } 23 24 private void recursiveDFS(Graph G, int v) 25 { 26 count++; 27 marked[v] = true; 28 for (int w : G.adj(v)) 29 { 30 if (!marked[w]) 31 { 32 edgeTo[w] = v; // depthFirstPath 需要 33 recursiveDFS(G, w); 34 } 35 } 36 } 37 38 public void nonRecursiveDFS(Graph G, int s) // 非递归版本 39 { 40 marked = new boolean[G.V()]; 41 Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];// 记录每个顶点处已经遍历到了哪一个链表节点 42 for (int v = 0; v < G.V(); v++) 43 adj[v] = G.adj(v).iterator(); 44 Stack<Integer> stack = new Stack<Integer>(); 45 marked[s] = true; 46 for (stack.push(s); !stack.isEmpty();) 47 { 48 int v = stack.peek(); 49 if (adj[v].hasNext()) 50 { 51 int w = adj[v].next(); 52 if (!marked[w]) 53 { 54 marked[w] = true; 55 stack.push(w); 56 } 57 } 58 else 59 stack.pop(); 60 } 61 } 62 63 public boolean marked(int v) 64 { 65 return marked[v]; 66 } 67 68 public int count() 69 { 70 return count; 71 } 72 73 public Iterable<Integer> pathTo(int v) 74 { 75 if (!hasPathTo(v)) 76 return null; 77 Stack<Integer> path = new Stack<Integer>(); 78 for (int x = v; x != s; x = edgeTo[x]) // 从终点向起点压栈,以后吐栈的时候就是从起点到终点 79 path.push(x); 80 path.push(s); 81 return path; 82 } 83 84 public static void main(String[] args) 85 { 86 In in = new In(args[0]); // 读入图文件和遍历起点 87 int s = Integer.parseInt(args[1]); 88 Graph G = new Graph(in); 89 class01 search = new class01(G, s); 90 for (int v = 0; v < G.V(); v++) // 通过检查是否所有的点都被遍历来确定图是否连通 91 { 92 if (search.marked(v)) 93 { 94 StdOut.printf("%d to %d: ", s, v); 95 for (int x : search.pathTo(v)) 96 { 97 if (x == s) 98 StdOut.print(x); 99 else 100 StdOut.print("-" + x); 101 } 102 StdOut.println(); 103 } 104 else 105 StdOut.printf("%d to %d: not connected ", s, v); 106 } 107 if (search.count() != G.V()) 108 StdOut.println(" Not connected. "); 109 else 110 StdOut.println(" Connected. "); 111 } 112 }
● 有向图的深度优先遍历
1 package package01; 2 3 import java.util.Iterator; 4 import edu.princeton.cs.algs4.In; 5 import edu.princeton.cs.algs4.StdOut; 6 import edu.princeton.cs.algs4.Digraph; 7 import edu.princeton.cs.algs4.Stack; 8 9 public class class01 10 { 11 private final int s; 12 private boolean[] marked; 13 private int count; 14 private int[] edgeTo; 15 16 public class01(Digraph G, int inputS) 17 { 18 s = inputS; 19 marked = new boolean[G.V()]; 20 edgeTo = new int[G.V()]; 21 recursiveDirectedDFS(G, s); 22 } 23 24 private void recursiveDirectedDFS(Digraph G, int v) 25 { 26 count++; 27 marked[v] = true; 28 for (int w : G.adj(v)) 29 { 30 if (!marked[w]) 31 { 32 edgeTo[w] = v; 33 recursiveDirectedDFS(G, w); 34 } 35 } 36 } 37 38 public void nonRecursiveDirectedDFS(Digraph G, int s) 39 { 40 marked = new boolean[G.V()]; 41 Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()]; 42 for (int v = 0; v < G.V(); v++) 43 adj[v] = G.adj(v).iterator(); 44 Stack<Integer> stack = new Stack<Integer>(); 45 marked[s] = true; 46 for (stack.push(s); !stack.isEmpty();) 47 { 48 int v = stack.peek(); 49 if (adj[v].hasNext()) 50 { 51 int w = adj[v].next(); 52 if (!marked[w]) 53 { 54 marked[w] = true; 55 stack.push(w); 56 } 57 } 58 else 59 stack.pop(); 60 } 61 } 62 63 public boolean marked(int v) 64 { 65 return marked[v]; 66 } 67 68 public int count() 69 { 70 return count; 71 } 72 73 public Iterable<Integer> pathTo(int v) 74 { 75 if (!hasPathTo(v)) 76 return null; 77 Stack<Integer> path = new Stack<Integer>(); 78 for (int x = v; x != s; x = edgeTo[x]) 79 path.push(x); 80 path.push(s); 81 return path; 82 } 83 84 public static void main(String[] args) 85 { 86 In in = new In(args[0]); 87 int s = Integer.parseInt(args[1]); 88 Graph G = new Graph(in); 89 class01 search = new class01(G, s); 90 for (int v = 0; v < G.V(); v++) 91 { 92 if (search.marked(v)) 93 { 94 StdOut.printf("%d to %d: ", s, v); 95 for (int x : search.pathTo(v)) 96 { 97 if (x == s) 98 StdOut.print(x); 99 else 100 StdOut.print("-" + x); 101 } 102 StdOut.println(); 103 } 104 else 105 StdOut.printf("%d to %d: not connected ", s, v); 106 } 107 if (search.count() != G.V()) 108 StdOut.println(" Not connected. "); 109 else 110 StdOut.println(" Connected. "); 111 } 112 }