《演算法》第四章部分程式 part 4
阿新 • • 發佈:2018-11-11
▶ 書中第四章部分程式,加上自己補充的程式碼,圖的深度優先遍歷
● 無向圖的深度優先遍歷,有向 / 無向圖程式碼僅若干方法名不同,包括遞迴和非遞迴版本,去掉了頂點有效性的檢查
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 24private 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\n", s, v); 106 } 107 if (search.count() != G.V()) 108 StdOut.println("\nNot connected.\n"); 109 else 110 StdOut.println("\nConnected.\n"); 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\n", s, v); 106 } 107 if (search.count() != G.V()) 108 StdOut.println("\nNot connected.\n"); 109 else 110 StdOut.println("\nConnected.\n"); 111 } 112 }