《算法》第四章部分程序 part 16

▶ 书中第四章部分程序,包括在加上自己补充的代码,Dijkstra 算法求有向 / 无向图最短路径,以及所有顶点对之间的最短路径

● Dijkstra 算法求有向图最短路径

 1 package package01;
 2 
 3 import edu.princeton.cs.algs4.In;
 4 import edu.princeton.cs.algs4.StdOut;
 5 import edu.princeton.cs.algs4.DirectedEdge;
 6 import edu.princeton.cs.algs4.EdgeWeightedDigraph;
 7 import edu.princeton.cs.algs4.Stack;
 8 import edu.princeton.cs.algs4.IndexMinPQ;
 9 
10 public class class01
11 {
12     private double[] distTo;                            // 起点到各顶点的距离
13     private DirectedEdge[] edgeTo;                      // 由于引入顶点 v 使得图中新增加的边记作 edgeTo[v]
14     private IndexMinPQ<Double> pq;                      // 搜索队列
15 
16     public class01(EdgeWeightedDigraph G, int s)
17     {
18         for (DirectedEdge e : G.edges())                // 确认所有变的权值为正
19         {
20             if (e.weight() < 0)
21                 throw new IllegalArgumentException("\n<Constructor> e.weight < 0.\n");
22         }
23         distTo = new double[G.V()];
24         edgeTo = new DirectedEdge[G.V()];
25         for (int v = 0; v < G.V(); v++)
26             distTo[v] = Double.POSITIVE_INFINITY;
27         distTo[s] = 0.0;                                // 起点
28         pq = new IndexMinPQ<Double>(G.V());
29         for (pq.insert(s, distTo[s]); !pq.isEmpty();)   // 每次从搜索队列中取出一个顶点,松弛与之相连的所有边
30         {
31             int v = pq.delMin();
32             for (DirectedEdge e : G.adj(v))
33                 relax(e);
34         }
35     }
36 
37     private void relax(DirectedEdge e)
38     {
39         int v = e.from(), w = e.to();
40         if (distTo[w] > distTo[v] + e.weight()) // 加入这条边会使起点到 w 的距离变短
41         {
42             distTo[w] = distTo[v] + e.weight(); // 加入该条边,更新 w 距离
43             edgeTo[w] = e;
44             if (pq.contains(w))                 // 若 w 已经在搜索队列中
45                 pq.decreaseKey(w, distTo[w]);   // 更新 w 在搜索队列中的权值为当前起点到 w 的距离
46             else
47                 pq.insert(w, distTo[w]);        // 否则将顶点 w 加入搜索队列
48         }
49     }
50 
51     public double distTo(int v)
52     {
53         return distTo[v];
54     }
55 
56     public boolean hasPathTo(int v)
57     {
58         return distTo[v] < Double.POSITIVE_INFINITY;
59     }
60 
61     public Iterable<DirectedEdge> pathTo(int v)                             // 生成起点到 v 的最短路径
62     {
63         if (!hasPathTo(v))
64             return null;
65         Stack<DirectedEdge> path = new Stack<DirectedEdge>();
66         for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()])   // 从 v 开始不断寻找父顶点,依次压入栈中
67             path.push(e);
68         return path;
69     }
70 
71     public static void main(String[] args)
72     {
73         In in = new In(args[0]);
74         int s = Integer.parseInt(args[1]);
75         EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
76         class01 sp = new class01(G, s);
77         for (int t = 0; t < G.V(); t++)
78         {
79             if (sp.hasPathTo(t))
80             {
81                 StdOut.printf("%d to %d (%.2f)  ", s, t, sp.distTo(t));
82                 for (DirectedEdge e : sp.pathTo(t))
83                     StdOut.print(e + "   ");
84                 StdOut.println();
85             }
86             else
87                 StdOut.printf("%d to %d no path\n", s, t);
88         }
89     }
90 }

● Dijkstra 算法求无向图最短路径

 1 package package01;
 2 
 3 import edu.princeton.cs.algs4.In;
 4 import edu.princeton.cs.algs4.StdOut;
 5 import edu.princeton.cs.algs4.Edge;
 6 import edu.princeton.cs.algs4.EdgeWeightedGraph;
 7 import edu.princeton.cs.algs4.Stack;
 8 import edu.princeton.cs.algs4.IndexMinPQ;
 9 
10 public class class01
11 {
12     private double[] distTo;
13     private Edge[] edgeTo;
14     private IndexMinPQ<Double> pq;
15 
16     public class01(EdgeWeightedGraph G, int s)
17     {
18         for (Edge e : G.edges())
19         {
20             if (e.weight() < 0)
21                 throw new IllegalArgumentException("\n<Constructor> e.weight < 0.\n");
22         }
23         distTo = new double[G.V()];
24         edgeTo = new Edge[G.V()];
25         for (int v = 0; v < G.V(); v++)
26             distTo[v] = Double.POSITIVE_INFINITY;
27         distTo[s] = 0.0;
28         pq = new IndexMinPQ<Double>(G.V());
29         for (pq.insert(s, distTo[s]); !pq.isEmpty();)
30         {
31             int v = pq.delMin();
32             for (Edge e : G.adj(v))
33                 relax(e, v);
34         }
35     }
36 
37     private void relax(Edge e, int v)           // 无向图没有 from 和 to 分量,需要给出新边已经遍历了的那个顶点
38     {
39         int w = e.other(v);
40         if (distTo[w] > distTo[v] + e.weight())
41         {
42             distTo[w] = distTo[v] + e.weight();
43             edgeTo[w] = e;
44             if (pq.contains(w))
45                 pq.decreaseKey(w, distTo[w]);
46             else
47                 pq.insert(w, distTo[w]);
48         }
49     }
50 
51     public double distTo(int v)
52     {
53         return distTo[v];
54     }
55 
56     public boolean hasPathTo(int v)
57     {
58         return distTo[v] < Double.POSITIVE_INFINITY;
59     }
60 
61     public Iterable<Edge> pathTo(int v)
62     {
63         if (!hasPathTo(v))
64             return null;
65         Stack<Edge> path = new Stack<Edge>();
66         int x = v;                              // 无向图需要变量记录父顶点,以便向回跳
67         for (Edge e = edgeTo[v]; e != null; e = edgeTo[x])
68         {
69             path.push(e);
70             x = e.other(x);
71         }
72         return path;
73     }
74 
75     public static void main(String[] args)
76     {
77         In in = new In(args[0]);
78         int s = Integer.parseInt(args[1]);
79         EdgeWeightedGraph G = new EdgeWeightedGraph(in);
80         class01 sp = new class01(G, s);
81         for (int t = 0; t < G.V(); t++)
82         {
83             if (sp.hasPathTo(t))
84             {
85                 StdOut.printf("%d to %d (%.2f)  ", s, t, sp.distTo(t));
86                 for (Edge e : sp.pathTo(t))
87                     StdOut.print(e + "   ");
88                 StdOut.println();
89             }
90             else
91                 StdOut.printf("%d to %d         no path\n", s, t);
92         }
93     }
94 }

● Dijkstra 算法求所有顶点对之间的最短路径

 1 package package01;
 2 
 3 import edu.princeton.cs.algs4.In;
 4 import edu.princeton.cs.algs4.StdOut;
 5 import edu.princeton.cs.algs4.DijkstraSP;
 6 import edu.princeton.cs.algs4.DirectedEdge;
 7 import edu.princeton.cs.algs4.EdgeWeightedDigraph;
 8 
 9 public class class01
10 {
11     private DijkstraSP[] all;
12 
13     public class01(EdgeWeightedDigraph G)
14     {
15         all = new DijkstraSP[G.V()];
16         for (int v = 0; v < G.V(); v++)     // 循环,每个点为起点都来一次 DijkstraSP
17             all[v] = new DijkstraSP(G, v);
18     }
19 
20     public Iterable<DirectedEdge> path(int s, int t)
21     {
22         return all[s].pathTo(t);
23     }
24 
25     public boolean hasPath(int s, int t)
26     {
27         return dist(s, t) < Double.POSITIVE_INFINITY;
28     }
29 
30     public double dist(int s, int t)
31     {
32         return all[s].distTo(t);
33     }
34 
35     public static void main(String[] args)
36     {
37         In in = new In(args[0]);
38         EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
39         class01 spt = new class01(G);
40         StdOut.printf("  ");                // 输出没对定点之间的最小路径距离
41         for (int v = 0; v < G.V(); v++)
42             StdOut.printf("%6d ", v);
43         StdOut.println();
44         for (int v = 0; v < G.V(); v++)
45         {
46             StdOut.printf("%3d: ", v);
47             for (int w = 0; w < G.V(); w++)
48             {
49                 if (spt.hasPath(v, w)) StdOut.printf("%6.2f ", spt.dist(v, w));
50                 else StdOut.printf("  Inf ");
51             }
52             StdOut.println();
53         }
54         StdOut.println();
55         for (int v = 0; v < G.V(); v++)     // 输出每对顶点之间最小路径
56         {
57             for (int w = 0; w < G.V(); w++)
58             {
59                 if (spt.hasPath(v, w))
60                 {
61                     StdOut.printf("%d to %d (%5.2f)  ", v, w, spt.dist(v, w));
62                     for (DirectedEdge e : spt.path(v, w))
63                         StdOut.print(e + "  ");
64                     StdOut.println();
65                 }
66                 else
67                     StdOut.printf("%d to %d no path\n", v, w);
68             }
69         }
70     }
71 }

猜你喜欢

转载自www.cnblogs.com/cuancuancuanhao/p/9830464.html