1. 程式人生 > >《演算法》第四章部分程式 part 4

《演算法》第四章部分程式 part 4

▶ 書中第四章部分程式,加上自己補充的程式碼,圖的深度優先遍歷

● 無向圖的深度優先遍歷,有向 / 無向圖程式碼僅若干方法名不同,包括遞迴和非遞迴版本,去掉了頂點有效性的檢查

  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\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 }