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

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

 package package01;

 import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.DirectedEdge;
import edu.princeton.cs.algs4.EdgeWeightedDigraph;
import edu.princeton.cs.algs4.Stack;
import edu.princeton.cs.algs4.IndexMinPQ; public class class01
{
private double[] distTo; // 起点到各顶点的距离
private DirectedEdge[] edgeTo; // 由于引入顶点 v 使得图中新增加的边记作 edgeTo[v]
private IndexMinPQ<Double> pq; // 搜索队列 public class01(EdgeWeightedDigraph G, int s)
{
for (DirectedEdge e : G.edges()) // 确认所有变的权值为正
{
if (e.weight() < 0)
throw new IllegalArgumentException("\n<Constructor> e.weight < 0.\n");
}
distTo = new double[G.V()];
edgeTo = new DirectedEdge[G.V()];
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
distTo[s] = 0.0; // 起点
pq = new IndexMinPQ<Double>(G.V());
for (pq.insert(s, distTo[s]); !pq.isEmpty();) // 每次从搜索队列中取出一个顶点,松弛与之相连的所有边
{
int v = pq.delMin();
for (DirectedEdge e : G.adj(v))
relax(e);
}
} private void relax(DirectedEdge e)
{
int v = e.from(), w = e.to();
if (distTo[w] > distTo[v] + e.weight()) // 加入这条边会使起点到 w 的距离变短
{
distTo[w] = distTo[v] + e.weight(); // 加入该条边,更新 w 距离
edgeTo[w] = e;
if (pq.contains(w)) // 若 w 已经在搜索队列中
pq.decreaseKey(w, distTo[w]); // 更新 w 在搜索队列中的权值为当前起点到 w 的距离
else
pq.insert(w, distTo[w]); // 否则将顶点 w 加入搜索队列
}
} public double distTo(int v)
{
return distTo[v];
} public boolean hasPathTo(int v)
{
return distTo[v] < Double.POSITIVE_INFINITY;
} public Iterable<DirectedEdge> pathTo(int v) // 生成起点到 v 的最短路径
{
if (!hasPathTo(v))
return null;
Stack<DirectedEdge> path = new Stack<DirectedEdge>();
for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) // 从 v 开始不断寻找父顶点,依次压入栈中
path.push(e);
return path;
} public static void main(String[] args)
{
In in = new In(args[0]);
int s = Integer.parseInt(args[1]);
EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
class01 sp = new class01(G, s);
for (int t = 0; t < G.V(); t++)
{
if (sp.hasPathTo(t))
{
StdOut.printf("%d to %d (%.2f) ", s, t, sp.distTo(t));
for (DirectedEdge e : sp.pathTo(t))
StdOut.print(e + " ");
StdOut.println();
}
else
StdOut.printf("%d to %d no path\n", s, t);
}
}
}

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

 package package01;

 import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Edge;
import edu.princeton.cs.algs4.EdgeWeightedGraph;
import edu.princeton.cs.algs4.Stack;
import edu.princeton.cs.algs4.IndexMinPQ; public class class01
{
private double[] distTo;
private Edge[] edgeTo;
private IndexMinPQ<Double> pq; public class01(EdgeWeightedGraph G, int s)
{
for (Edge e : G.edges())
{
if (e.weight() < 0)
throw new IllegalArgumentException("\n<Constructor> e.weight < 0.\n");
}
distTo = new double[G.V()];
edgeTo = new Edge[G.V()];
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
distTo[s] = 0.0;
pq = new IndexMinPQ<Double>(G.V());
for (pq.insert(s, distTo[s]); !pq.isEmpty();)
{
int v = pq.delMin();
for (Edge e : G.adj(v))
relax(e, v);
}
} private void relax(Edge e, int v) // 无向图没有 from 和 to 分量,需要给出新边已经遍历了的那个顶点
{
int w = e.other(v);
if (distTo[w] > distTo[v] + e.weight())
{
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
if (pq.contains(w))
pq.decreaseKey(w, distTo[w]);
else
pq.insert(w, distTo[w]);
}
} public double distTo(int v)
{
return distTo[v];
} public boolean hasPathTo(int v)
{
return distTo[v] < Double.POSITIVE_INFINITY;
} public Iterable<Edge> pathTo(int v)
{
if (!hasPathTo(v))
return null;
Stack<Edge> path = new Stack<Edge>();
int x = v; // 无向图需要变量记录父顶点,以便向回跳
for (Edge e = edgeTo[v]; e != null; e = edgeTo[x])
{
path.push(e);
x = e.other(x);
}
return path;
} public static void main(String[] args)
{
In in = new In(args[0]);
int s = Integer.parseInt(args[1]);
EdgeWeightedGraph G = new EdgeWeightedGraph(in);
class01 sp = new class01(G, s);
for (int t = 0; t < G.V(); t++)
{
if (sp.hasPathTo(t))
{
StdOut.printf("%d to %d (%.2f) ", s, t, sp.distTo(t));
for (Edge e : sp.pathTo(t))
StdOut.print(e + " ");
StdOut.println();
}
else
StdOut.printf("%d to %d no path\n", s, t);
}
}
}

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

 package package01;

 import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.DijkstraSP;
import edu.princeton.cs.algs4.DirectedEdge;
import edu.princeton.cs.algs4.EdgeWeightedDigraph; public class class01
{
private DijkstraSP[] all; public class01(EdgeWeightedDigraph G)
{
all = new DijkstraSP[G.V()];
for (int v = 0; v < G.V(); v++) // 循环,每个点为起点都来一次 DijkstraSP
all[v] = new DijkstraSP(G, v);
} public Iterable<DirectedEdge> path(int s, int t)
{
return all[s].pathTo(t);
} public boolean hasPath(int s, int t)
{
return dist(s, t) < Double.POSITIVE_INFINITY;
} public double dist(int s, int t)
{
return all[s].distTo(t);
} public static void main(String[] args)
{
In in = new In(args[0]);
EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
class01 spt = new class01(G);
StdOut.printf(" "); // 输出没对定点之间的最小路径距离
for (int v = 0; v < G.V(); v++)
StdOut.printf("%6d ", v);
StdOut.println();
for (int v = 0; v < G.V(); v++)
{
StdOut.printf("%3d: ", v);
for (int w = 0; w < G.V(); w++)
{
if (spt.hasPath(v, w)) StdOut.printf("%6.2f ", spt.dist(v, w));
else StdOut.printf(" Inf ");
}
StdOut.println();
}
StdOut.println();
for (int v = 0; v < G.V(); v++) // 输出每对顶点之间最小路径
{
for (int w = 0; w < G.V(); w++)
{
if (spt.hasPath(v, w))
{
StdOut.printf("%d to %d (%5.2f) ", v, w, spt.dist(v, w));
for (DirectedEdge e : spt.path(v, w))
StdOut.print(e + " ");
StdOut.println();
}
else
StdOut.printf("%d to %d no path\n", v, w);
}
}
}
}

《算法》第四章部分程序 part 16的更多相关文章

  1. 《算法》第四章部分程序 part 19

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,有边权有向图的邻接矩阵,FloydWarshall 算法可能含负环的有边权有向图任意两点之间的最短路径 ● 有边权有向图的邻接矩阵 package p ...

  2. 《算法》第四章部分程序 part 18

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,在有权有向图中寻找环,Bellman - Ford 算法求最短路径,套汇算法 ● 在有权有向图中寻找环 package package01; impo ...

  3. 《算法》第四章部分程序 part 15

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...

  4. 《算法》第四章部分程序 part 14

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种 Prim 算法求最小生成树 ● 简单 Prim 算法求最小生成树 package package01; import edu.princeton ...

  5. 《算法》第四章部分程序 part 10

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,包括无向图连通分量,Kosaraju - Sharir 算法.Tarjan 算法.Gabow 算法计算有向图的强连通分量 ● 无向图连通分量 pack ...

  6. 《算法》第四章部分程序 part 9

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法 ● 拓扑排序 1 package package01; import edu.princeton.cs.algs4.Digraph ...

  7. 《算法》第四章部分程序 part 17

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题 ● 无环图最短 / 最长路径通用程序 pa ...

  8. 《算法》第四章部分程序 part 13

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的前序.后序和逆后续遍历,以及传递闭包 ● 图的前序.后序和逆后续遍历 package package01; import edu.princeto ...

  9. 《算法》第四章部分程序 part 12

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的几种补充数据结构,包括无向 / 有向符号图,有权边结构,有边权有向图 ● 无向符号图 package package01; import edu. ...

随机推荐

  1. Python进行RSA安装加密

    一.下载ez_setup.py(http://peak.telecommunity.com/dist/ez_setup.py) 二.用python解释执行它 (如使用IDLE打开该py文件,按F5解释 ...

  2. LeetCode——4. Median of Two Sorted Arrays

    一.题目链接:https://leetcode.com/problems/median-of-two-sorted-arrays 二.题目大意: 给定两个排序过的数组,求出两个数组的中位数,要求时间复 ...

  3. elasticsearch 口水篇(4)java客户端 - 原生esClient

    上一篇(elasticsearch 口水篇(3)java客户端 - Jest)Jest是第三方客户端,基于REST Api进行调用(httpClient),本篇简单介绍下elasticsearch原生 ...

  4. vc++获取网页源码

    1. 获取网页源码的步骤: com组件的初始化 创建WinHttpRequest对象 创建并实例化WinHttpRequest组件 调用Open方法打开连接 调用Send方法发送请求 使用Respon ...

  5. java高并发编程(二)

    马士兵java并发编程的代码,照抄过来,做个记录. 一.分析下面面试题 /** * 曾经的面试题:(淘宝?) * 实现一个容器,提供两个方法,add,size * 写两个线程,线程1添加10个元素到容 ...

  6. 客户端负载均衡Feign之一:申明式服务调用Feign入门示例

    Spring Cloud提供了Ribbon和Feign作为客户端的负载均衡. 前面使用了Ribbon做客户端负载均衡,使用Hystrix做容错保护,这两者被作为基础工具类框架被广泛地应用在各个微服务的 ...

  7. 学习笔记之Swagger

    World's Most Popular API Framework | Swagger https://swagger.io/ Swagger is the world’s largest fram ...

  8. 个人知识管理PKM:收集、消化、应用、创新

                                                          个人知识管理PKM:收集.消化.应用.创新 准备工作1.制作知识分类体系(在线博客分类.本地 ...

  9. html标签SEO规范

    原文地址:http://blog.sina.com.cn/s/blog_6c3898dd0100whr7.html 1.<!--页面注解--> 2.<html> 3.<h ...

  10. golang中defer的理解

    在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用.因此,defer通常用来释放函数内 ...