zoukankan      html  css  js  c++  java
  • 《算法》第四章部分程序 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("
    <Constructor> e.weight < 0.
    ");
    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
    ", 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("
    <Constructor> e.weight < 0.
    ");
    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
    ", 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
    ", v, w);
    68             }
    69         }
    70     }
    71 }
  • 相关阅读:
    Django-models,继承AbstractUser类
    Django-views,用户认证,login_requierd()
    django前篇
    jquery插件
    jquery事件及插件
    jquery操作元素
    jquery选择器筛选器
    js作用域与作用域链
    js之DOM(二)
    bootstrap
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9830464.html
Copyright © 2011-2022 走看看