▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法
● 拓扑排序 1
1 package package01; 2 3 import edu.princeton.cs.algs4.Digraph; 4 import edu.princeton.cs.algs4.SymbolDigraph; 5 import edu.princeton.cs.algs4.DirectedCycle; 6 import edu.princeton.cs.algs4.DepthFirstOrder; 7 import edu.princeton.cs.algs4.EdgeWeightedDigraph; 8 import edu.princeton.cs.algs4.EdgeWeightedDirectedCycle; 9 10 public class class01 11 { 12 private Iterable<Integer> order; // 拓扑排序的结果 13 private int[] rank; // 顶点 v 在拓扑排序中的序号为 rank[v] 14 15 public class01(Digraph G) // 从有向图生成拓扑排序 16 { 17 DirectedCycle finder = new DirectedCycle(G); // 存在环则不能排序 18 if (!finder.hasCycle()) 19 { 20 DepthFirstOrder dfs = new DepthFirstOrder(G); // 做 G 的深度优先搜索 21 order = dfs.reversePost(); // 取逆后序依次标号 22 rank = new int[G.V()]; 23 int i = 0; 24 for (int v : order) 25 rank[v] = i++; 26 } 27 } 28 29 public class01(EdgeWeightedDigraph G) // 从加权边有向图生成拓扑排序(算法一样,只是数据结构不同) 30 { 31 EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G); 32 if (!finder.hasCycle()) 33 { 34 DepthFirstOrder dfs = new DepthFirstOrder(G); 35 order = dfs.reversePost(); 36 rank = new int[G.V()]; 37 int i = 0; 38 for (int v : order) 39 rank[v] = i++; 40 } 41 } 42 43 public Iterable<Integer> order() 44 { 45 return order; 46 } 47 48 public boolean hasOrder() 49 { 50 return order != null; 51 } 52 53 public int rank(int v) 54 { 55 return hasOrder() ? rank[v] : -1; 56 } 57 58 public static void main(String[] args) 59 { 60 String filename = args[0]; 61 String delimiter = args[1]; // 分隔符 62 SymbolDigraph sg = new SymbolDigraph(filename, delimiter); 63 class01 topological = new class01(sg.digraph()); 64 for (int v : topological.order()) 65 System.out.println(sg.nameOf(v)); 66 } 67 }
● 拓扑排序 2
1 package package01; 2 3 import edu.princeton.cs.algs4.StdOut; 4 import edu.princeton.cs.algs4.StdRandom; 5 import edu.princeton.cs.algs4.DigraphGenerator; 6 import edu.princeton.cs.algs4.Digraph; 7 import edu.princeton.cs.algs4.Queue; 8 import edu.princeton.cs.algs4.DirectedEdge; 9 import edu.princeton.cs.algs4.EdgeWeightedDigraph; 10 11 public class class01 12 { 13 private Queue<Integer> order; 14 private int[] rank; 15 16 public class01(Digraph G) 17 { 18 order = new Queue<Integer>(); 19 rank = new int[G.V()]; 20 int[] indegree = new int[G.V()]; 21 for (int v = 0; v < G.V(); v++) 22 indegree[v] = G.indegree(v); 23 int count = 0; 24 Queue<Integer> queue = new Queue<Integer>(); 25 for (int v = 0; v < G.V(); v++) // 收集所有没有前提条件的顶点 26 { 27 if (indegree[v] == 0) 28 queue.enqueue(v); 29 } 30 for (; !queue.isEmpty();) 31 { 32 int v = queue.dequeue(); 33 order.enqueue(v); // 事件 v 完成,将其放入输出队列, 并给一个序号 34 rank[v] = count++; 35 for (int w : G.adj(v)) // 所有紧接着 v 的事件的前提条件减少 1 36 { 37 indegree[w]--; 38 if (indegree[w] == 0) // 收集此时没有前提条件的事件 39 queue.enqueue(w); 40 } 41 } 42 if (count != G.V()) // 遍历结束,还有顶点有入度,说明存在环 43 order = null; 44 } 45 46 public class01(EdgeWeightedDigraph G) 47 { 48 order = new Queue<Integer>(); 49 rank = new int[G.V()]; 50 int[] indegree = new int[G.V()]; 51 for (int v = 0; v < G.V(); v++) 52 indegree[v] = G.indegree(v); 53 int count = 0; 54 Queue<Integer> queue = new Queue<Integer>(); 55 for (int v = 0; v < G.V(); v++) 56 { 57 if (indegree[v] == 0) 58 queue.enqueue(v); 59 } 60 for (; !queue.isEmpty();) 61 { 62 int v = queue.dequeue(); 63 order.enqueue(v); 64 rank[v] = count++; 65 for (DirectedEdge e : G.adj(v)) 66 { 67 int w = e.to(); 68 indegree[w]--; 69 if (indegree[w] == 0) 70 queue.enqueue(w); 71 } 72 } 73 if (count != G.V()) 74 order = null; 75 } 76 77 public Iterable<Integer> order() 78 { 79 return order; 80 } 81 82 public boolean hasOrder() 83 { 84 return order != null; 85 } 86 87 public int rank(int v) 88 { 89 return hasOrder() ? rank[v] : -1; 90 } 91 92 public static void main(String[] args) 93 { 94 int V = Integer.parseInt(args[0]); // 生成DAG G(V,E),再添加 F 条边 95 int E = Integer.parseInt(args[1]); 96 int F = Integer.parseInt(args[2]); 97 Digraph G1 = DigraphGenerator.dag(V, E); // G1 是无边圈的 98 EdgeWeightedDigraph G2 = new EdgeWeightedDigraph(V);// G2 有边权的 99 for (int v = 0; v < G1.V(); v++) 100 { 101 for (int w : G1.adj(v)) 102 G2.addEdge(new DirectedEdge(v, w, 0.0)); 103 } 104 for (int i = 0; i < F; i++) 105 { 106 int v = StdRandom.uniform(V); 107 int w = StdRandom.uniform(V); 108 G1.addEdge(v, w); 109 G2.addEdge(new DirectedEdge(v, w, 0.0)); 110 } 111 StdOut.println(G1); 112 StdOut.println(); 113 StdOut.println(G2); 114 class01 topological1 = new class01(G1); // 分别计算 G1 和 G2 的 115 if (!topological1.hasOrder()) 116 StdOut.println("Not a DAG"); 117 else 118 { 119 StdOut.print("Topological order: "); 120 for (int v : topological1.order()) 121 StdOut.print(v + " "); 122 StdOut.println(); 123 } 124 class01 topological2 = new class01(G2); 125 if (!topological2.hasOrder()) 126 StdOut.println("Not a DAG"); 127 else 128 { 129 StdOut.print("Topological order: "); 130 for (int v : topological2.order()) 131 StdOut.print(v + " "); 132 StdOut.println(); 133 } 134 } 135 }