最短路径的java代码实现

news/2025/1/6 5:50:55/

1.最短路径定义及性质

有了加权有向图之后,我们立刻就能联想到实际生活中的使用场景,例如在一副地图中,找到顶点a与地点b之间的路径,这条路径可以是距离最短,也可以是时间最短,也可以是费用最小等,如果我们把 距离/时间/费用看做是成本,那么就需要找到地点a和地点b之间成本最小的路径,也就是我们接下来要解决的最短路径问题。

定义:
在一副加权有向图中,从顶点s到顶点t的最短路径是所有从顶点s到顶点t的路径中总权重最小的那条路径
性质:
1.路径具有方向性;
2.权重不一定等价于距离。权重可以是距离、时间、花费等内容,权重最小指的是成本最低
3.只考虑连通图。一副图中并不是所有的顶点都是可达的,如果s和t不可达,那么它们之间也就不存在最短路径,为了简化问题,这里只考虑连通图。
4.最短路径不一定是唯一的。从一个顶点到达另外一个顶点的权重最小的路径可能会有很多条,这里只需要找出一条即可。
最短路径树:
给定一副加权有向图和一个顶点s,以s为起点的一棵最短路径树是图的一副子图,它包含顶点s以及从s可达的所有顶点。这棵有向树的根结点为s,树的每条路径都是有向图中的一条最短路径。

2.最短路径树API设计

计算最短路径树的经典算法是dijstra算法

类名DijkstraSP
构造方法public DijkstraSP(EdgeWeightedDigraph G, int s):根据一副加权有向图G和顶点s,创建一个计算顶点为s的最短路径树对象
成员方法1.private void relax(EdgeWeightedDigraph G, int v):松弛图G中的顶点v
2.public double distTo(int v):获取从顶点s到顶点v的最短路径的总权重
3.public boolean hasPathTo(int v):判断从顶点s到顶点v是否可达
4.public Queue pathTo(int v):查询从起点s到顶点v的最短路径中所有的边
成员变量1.private DirectedEdge[] edgeTo: 索引代表顶点,值表示从顶点s到当前顶点的最短路径上的最后一条边
2.private double[] distTo: 索引代表顶点,值从顶点s到当前顶点的最短路径的总权重
3.private IndexMinPriorityQueue pq:存放树中顶点与非树中顶点之间的有效横切边

3.松弛技术

松弛这个词来源于生活:一条橡皮筋沿着两个顶点的某条路径紧紧展开,如果这两个顶点之间的路径不止一条,还有存在更短的路径,那么把皮筋转移到更短的路径上,皮筋就可以放松了。松弛这种简单的原理刚好可以用来计算最短路径树。
在我们的API中,需要用到两个成员变量edgeTo和distTo,分别存储边和权重。一开始给定一幅图G和顶点s,我们只知道图的边以及这些边的权重,其他的一无所知,此时初始化顶点s到顶点s的最短路径的总权重disto[s]=0;顶点s到其他顶点的总权重默认为无穷大,随着算法的执行,不断的使用松弛技术处理图的边和顶点,并按一定的条件更新edgeTo和distTo中的数据,最终就可以得到最短路劲树。
边的松弛:
放松边v->w意味着检查从s到w的最短路径是否先从s到v,然后再从v到w?
如果是,则v-w这条边需要加入到最短路径树中,更新edgeTo和distTo中的内容:edgeTo[w]=表示v->w这条边的
DirectedEdge对象,distTo[w]=distTo[v]+v->w这条边的权重;
如果不是,则忽略v->w这条边。
在这里插入图片描述
顶点的松弛:
顶点的松弛是基于边的松弛完成的,只需要把某个顶点指出的所有边松弛,那么该顶点就松弛完毕。例如要松弛顶
点v,只需要遍历v的邻接表,把每一条边都松弛,那么顶点v就松弛了。

在这里插入图片描述

4.Dijstra算法实现

Disjstra算法的实现和Prim算法很类似,构造最短路径树的每一步都是向这棵树中添加一条新的边,而这条新的边是有效横切边pq队列中的权重最小的边。

public class DijkstraSP {//索引代表顶点,值表示从顶点s到当前顶点的最短路径上的最后一条边private DirectedEdge[] edgeTo;//索引代表顶点,值从顶点s到当前顶点的最短路径的总权重private double[] distTo;//存放树中顶点与非树中顶点之间的有效横切边private IndexMinPriorityQueue<Double> pq;//根据一副加权有向图G和顶点s,创建一个计算顶点为s的最短路径树对象public DijkstraSP(EdgeWeightedDigraph G, int s){//创建一个和图的顶点数一样大小的DirectedEdge数组,表示边this.edgeTo = new DirectedEdge[G.V()];//创建一个和图的顶点数一样大小的double数组,表示权重,并且初始化数组中的内容为无穷大,无穷大即表示不存在这样的边this.distTo = new double[G.V()];for (int i = 0; i < distTo.length; i++) {distTo[i] = Double.POSITIVE_INFINITY;}//创建一个和图的顶点数一样大小的索引优先队列,存储有效横切边this.pq = new IndexMinPriorityQueue<>(G.V());//默认让顶点s进入树中,但s顶点目前没有与树中其他的顶点相连接,因此初始化distTo[s]=0.0distTo[s] = 0.0;//使用顶点s和权重0.0初始化pqpq.insert(s, 0.0);//遍历有效边队列while (!pq.isEmpty()) {//松弛图G中的顶点relax(G, pq.delMin());}}//松弛图G中的顶点vprivate void relax(EdgeWeightedDigraph G, int v){//松弛顶点v就是松弛顶点v邻接表中的每一条边,遍历邻接表for (DirectedEdge e : G.adj(v)) {//获取边e的终点int w = e.to();//起点s到顶点w的权重是否大于起点s到顶点v的权重+边e的权重,如果大于,则修改s->w的路径:edgeTo[w]=e,并修改distTo[v] = distTo[v]+e.weitht(),如果不大于,则忽略if (distTo(w)>distTo(v)+e.weight()){distTo[w]=distTo[v]+e.weight();edgeTo[w]=e;//如果顶点w已经存在于优先队列pq中,则重置顶点w的权重if (pq.contains(w)){pq.changeItem(w,distTo(w));}else{//如果顶点w没有出现在优先队列pq中,则把顶点w及其权重加入到pq中pq.insert(w,distTo(w));}}}}//获取从顶点s到顶点v的最短路径的总权重public double distTo(int v){return distTo[v];}//判断从顶点s到顶点v是否可达public boolean hasPathTo(int v){return distTo[v]<Double.POSITIVE_INFINITY;}//查询从起点s到顶点v的最短路径中所有的边public Queue<DirectedEdge> pathTo(int v){//如果顶点s到v不可达,则返回nullif (!hasPathTo(v)){return null;}//创建队列Queue保存最短路径的边Queue<DirectedEdge> edges = new Queue<>();//从顶点v开始,逆向寻找,一直找到顶点s为止,而起点s为最短路劲树的根结点,所以edgeTo[s]=null;DirectedEdge e=null;while(true){e = edgeTo[v];if (e==null){break;}edges.enqueue(e);v = e.from();}return edges;}}//测试代码public class DijkstraSpTest {public static void main(String[] args) throws Exception {//创建输入流BufferedReader reader = new BufferedReader(newInputStreamReader(DijkstraSpTest.class.getClassLoader().getResourceAsStream("min_route_test.txt")));//读取顶点数目,初始化EdgeWeightedDigraph图int number = Integer.parseInt(reader.readLine());EdgeWeightedDigraph G = new EdgeWeightedDigraph(number);//读取边的数目int edgeNumber = Integer.parseInt(reader.readLine());//循环读取每一条边,并调用addEdge方法for (int i = 0; i < edgeNumber; i++) {String line = reader.readLine();int v = Integer.parseInt(line.split(" ")[0]);int w = Integer.parseInt(line.split(" ")[1]);double weight = Double.parseDouble(line.split(" ")[2]);G.addEdge(new DirectedEdge(v, w, weight));}//根据图G和顶点0,构建DijkstraSP对象DijkstraSP dsp = new DijkstraSP(G, 0);//获取起点0到顶点6的最短路径Queue<DirectedEdge> edges = dsp.pathTo(6);//打印输出for (DirectedEdge edge : edges) {System.out.println(edge.from() + "->" + edge.to() + "::" + edge.weight());}}
}

http://www.ppmy.cn/news/8308.html

相关文章

通信领域相关的英语缩略语

ACK——Acknowledge character 应答信号&#xff1b;确认字符 ACS——Automatic Channel Selection 自动信道选择 AGC——Automatic Gain Control 自动增益控制 ALC——Automatic Level Control 自动电平控制 ALE——Automatic Link Establishment 自动链路建立 ALM——Automat…

Diffusion Model原理详解及源码解析

&#x1f34a;作者简介&#xff1a;秃头小苏&#xff0c;致力于用最通俗的语言描述问题 &#x1f34a;专栏推荐&#xff1a;深度学习网络原理与实战 &#x1f34a;近期目标&#xff1a;写好专栏的每一篇文章 &#x1f34a;支持小苏&#xff1a;点赞&#x1f44d;&#x1f3fc;、…

Casting out Primes: Bignum Arithmetic for Zero-Knowledge Proofs学习笔记

1. 引言 Polygon zero团队 Daniel Lubarov 和 Polygon zkEVM团队 Jordi Baylina 2022年10月联合发表的论文 《Casting out Primes: Bignum Arithmetic for Zero-Knowledge Proofs》。 受“casting out nines” 技术——做对9取模运算并提供概率性结果&#xff0c;启发&#x…

【C++升级之路】第五篇:C/C++内存管理(new和delete的实现原理)

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;C/C内存分布&#xff0c;C/C动态内存管理方法&#xff0c;C动态内存管理方法底层函数operator new 和operat…

2022年终总结:少年不惧岁月长,彼方尚有荣光在。

2022年终总结&#xff1a;少年不惧岁月长&#xff0c;彼方尚有荣光在。 &#x1f3ac; 博客主页&#xff1a;王同学要努力 &#x1f3ac;个人简介&#xff1a;大三小白&#xff0c;喜欢前端 &#xff0c;热爱分享 &#x1f3a5; 本文由 王同学要努力 原创&#xff0c;首发于…

常用Stream流

Stream流 数据源 数据处理 数据结果 filter 过滤 limit 取前几 sorted 排序 max、min、count map 对集合中的元素进行特定的操作 reduce 将所有的元素按照传入的逻辑进行处理&#xff0c;并且会把结果合并成一个值进行返回 collection 基于目标集合生成新的数组 public class…

04 业务服务注册到 nacos 默认权重为0, 导致 gateway 获取不到业务服务

前言 最近搭建 xxx服务 的时候碰到了一个这样的问题 某业务服务 启动之后, 注册到 nacos, 然后 从 gateway 来获取该服务却报错, 没有找到 xxx服务 之前 记录了一个 todo, 今天 来梳理一下 主要是会涉及到我们关注的问题, 以及 服务的注册流程 不会大而全 nacos 服务实…

mysql基础笔记3

连接查询 &#xff08;1&#xff09;内连接 找同一个字段 select 表1字段1,。。。。表2 字段...... from 表1&#xff0c;表2 where 条件 表1.字段表2.字段 &#xff08;2&#xff09;外连接 &#xff08;1&#xff09;左外连接 左表中的所有数组 select section,logi…