最短路

最短路问题分为俩个模块,单源最短路和多源最短路问题,而单源最短路中又分为4种算法,分别总结一下

单源最短路问题

单源最短路问题(又称为SSSP问题),给定一张有向图,n个点,m个边,节点以[1,n]之间的连续整数编号,(x,y,z)描述一条从x出发,到达y,长度为z的有向边。设1号点为起点,求长度为n的数组dist,其中dist[i]表示从起点1到节点i的最短路径的长度

Dijkstra算法

算法的基本流程:

  1. 初始化dist[1] = 0,其余节点都为正无穷大
  2. 找到应该未标记的,dist[x]最小节点x,然后标记节点x
  3. 扫描节点x的所有出边(x,y,z),若dist[y]>distp[x]+z,则使用dist[x]+z更新dist[y]
  4. 重复上述2-3,直到所有节点都被标记

不难发现,基于贪心,故只适用于边的长度为非负

当边长都为非负数的时候,全局最小值已经不能被其他节点更新,故在第一步中选出的节点x必然满足:dist[x]已经是起点到x的最短路径,进行不断的选择,标记,拓展,最终得到每个节点的最短路径的长度

package 最短路;public class Dijkstra {/** 参数adjMatrix:为图的权重矩阵,权值为-1的两个顶点表示不能直接相连* 函数功能:返回顶点0到其它所有顶点的最短距离,其中顶点0到顶点0的最短距离为0*/public int[] getShortestPaths(int[][] adjMatrix) {int[] result = new int[adjMatrix.length];   //用于存放顶点0到其它顶点的最短距离boolean[] used = new boolean[adjMatrix.length];  //用于判断顶点是否被遍历used[0] = true;  //表示顶点0已被遍历for(int i = 1;i < adjMatrix.length;i++) {result[i] = adjMatrix[0][i];used[i] = false;}for(int i = 1;i < adjMatrix.length;i++) {int min = Integer.MAX_VALUE;    //用于暂时存放顶点0到i的最短距离,初始化为Integer型最大值int k = 0;for(int j = 1;j < adjMatrix.length;j++) {  //找到顶点0到其它顶点中距离最小的一个顶点if(!used[j] && result[j] != -1 && min > result[j]) {min = result[j];k = j;}}used[k] = true;    //将距离最小的顶点,记为已遍历for(int j = 1;j < adjMatrix.length;j++) {  //然后,将顶点0到其它顶点的距离与加入中间顶点k之后的距离进行比较,更新最短距离if(!used[j]) {  //当顶点j未被遍历时//首先,顶点k到顶点j要能通行;这时,当顶点0到顶点j的距离大于顶点0到k再到j的距离或者顶点0无法直接到达顶点j时,更新顶点0到顶点j的最短距离if(adjMatrix[k][j] != -1 && (result[j] > min + adjMatrix[k][j] || result[j] == -1))result[j] = min + adjMatrix[k][j];}}}return result;}public static void main(String[] args) {Dijkstra test = new Dijkstra();int[][] adjMatrix = {{0,6,3,-1,-1,-1},{6,0,2,5,-1,-1},{3,2,0,3,4,-1},{-1,5,3,0,2,3},{-1,-1,4,2,0,5},{-1,-1,-1,3,5,0}};int[] result = test.getShortestPaths(adjMatrix);System.out.println("顶点0到图中所有顶点之间的最短距离为:");for(int i = 0;i < result.length;i++)System.out.print(result[i]+" ");}
}

存在负权边,Bellman-Ford

基于迭代思想:

  1. 扫描所有边(x,y,z),若dist[y]>dist[x]+z,则用dist[x]+z更新dist[y]
  2. 重复上面的步骤,直到没有更新操作发生
package 最短路;import java.util.Scanner;public class BellmanFord {public long[] result;       //用于存放第0个顶点到其它顶点之间的最短距离//内部类,表示图的一条加权边class edge {public int a;   //边的起点public int b;   //边的终点public int value;  //边的权值edge(int a, int b, int value) {this.a = a;this.b = b;this.value = value;}}//返回第0个顶点到其它所有顶点之间的最短距离public boolean getShortestPaths(int n, edge[] A) {result = new long[n];for (int i = 1; i < n; i++)result[i] = Integer.MAX_VALUE;  //初始化第0个顶点到其它顶点之间的距离为无穷大,此处用Integer型最大值表示for (int i = 1; i < n; i++) {for (int j = 0; j < A.length; j++) {if (result[A[j].b] > result[A[j].a] + A[j].value)result[A[j].b] = result[A[j].a] + A[j].value;}}boolean judge = true;for (int i = 1; i < n; i++) {   //判断给定图中是否存在负环if (result[A[i].b] > result[A[i].a] + A[i].value) {judge = false;break;}}return judge;}public static void main(String[] args) {BellmanFord test = new BellmanFord();Scanner in = new Scanner(System.in);System.out.println("请输入一个图的顶点总数n和边总数p:");int n = in.nextInt();int p = in.nextInt();edge[] A = new edge[p];System.out.println("请输入具体边的数据:");for (int i = 0; i < p; i++) {int a = in.nextInt();int b = in.nextInt();int value = in.nextInt();A[i] = test.new edge(a, b, value);}if (test.getShortestPaths(n, A)) {for (int i = 0; i < test.result.length; i++)System.out.print(test.result[i] + " ");} elseSystem.out.println("给定图存在负环,没有最短距离");}}

存在负权边,SPFA

实际上,SPFA算法在国际上统称为“队列优化的Bellman-Ford算法,仅在中国称为”SPFA“算法
流程如下:

  1. 建立一个队列,起初队列中只含有起点1
  2. 取出队头节点x,扫描它的所有出边(x,y,z)若,dist[y]>dist[x]+z,则使用dist[x]+z更新dist[y]。同时,若y不在队列中,则把y入队
  3. 重复,直到队列为空
package 最短路;import java.util.ArrayList;
import java.util.Scanner;public class SPFA {public long[] result;         //用于得到第s个顶点到其它顶点之间的最短距离//内部类,用于存放图的具体边数据class edge {public int a;  //边的起点public int b;  //边的终点public int value;   //边的权值edge(int a, int b, int value) {this.a = a;this.b = b;this.value = value;}}/** 参数n:给定图的顶点个数* 参数s:求取第s个顶点到其它所有顶点之间的最短距离* 参数edge:给定图的具体边* 函数功能:如果给定图不含负权回路,则可以得到最终结果,如果含有负权回路,则不能得到最终结果*/public boolean getShortestPaths(int n, int s, edge[] A) {ArrayList<Integer> list = new ArrayList<Integer>();result = new long[n];boolean[] used = new boolean[n];int[] num = new int[n];for(int i = 0;i < n;i++) {result[i] = Integer.MAX_VALUE;used[i] = false;}result[s] = 0;     //第s个顶点到自身距离为0used[s] = true;    //表示第s个顶点进入数组队num[s] = 1;       //表示第s个顶点已被遍历一次list.add(s);      //第s个顶点入队while(list.size() != 0) {int a = list.get(0);   //获取数组队中第一个元素list.remove(0);         //删除数组队中第一个元素for(int i = 0;i < A.length;i++) {//当list数组队的第一个元素等于边A[i]的起点时if(a == A[i].a && result[A[i].b] > result[A[i].a] + A[i].value) {result[A[i].b] = result[A[i].a] + A[i].value;if(!used[A[i].b]) {list.add(A[i].b);num[A[i].b]++;if(num[A[i].b] > n)return false;used[A[i].b] = true;   //表示边A[i]的终点b已进入数组队}}}used[a] = false;        //顶点a出数组对}return true;}public static void main(String[] args) {SPFA test = new SPFA();Scanner in = new Scanner(System.in);System.out.println("请输入一个图的顶点总数n起点下标s和边总数p:");int n = in.nextInt();int s = in.nextInt();int p = in.nextInt();edge[] A = new edge[p];System.out.println("请输入具体边的数据:");for(int i = 0;i < p;i++) {int a = in.nextInt();int b = in.nextInt();int value = in.nextInt();A[i] = test.new edge(a, b, value);}if(test.getShortestPaths(n, s, A)) {for(int i = 0;i < test.result.length;i++)System.out.print(test.result[i]+" ");} elseSystem.out.println("给定图存在负环,没有最短距离");}
}

最短路问题——Java语言实现相关推荐

  1. Java语言中的数据类型

    Java语言是一种强调数据类型的语言,在声明任何变量时,必须将该变量定义为一种数据类型. Java中的数据类型包括基本类型和对象类型,基本类型总共有8种,其中4种整形.1种字符型.2种浮点型.1种布尔 ...

  2. java语言环境变量_JAVA语言环境变量的设置教程

    本文主要向大家介绍了JAVA语言环境变量的设置教程,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 安装JDK到目录,我这里是C:\Java 右键点击计算机属性 在系统变量里面建 JA ...

  3. java语言的实现机制_JAVA语言之Java NIO的工作机制和实现原理介绍

    本文主要向大家介绍了JAVA语言之Java NIO的工作机制和实现原理介绍,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 前言 本文只简单介绍NIO的原理实现和基本工作流程 I/O和 ...

  4. Java语言的基础知识9

    第十一章(线程) 1.通过String name=Thread.currentThread().getName();来获取当前线程的名称. 2.多次启动一个线程或者启动一个已经运行的线程是非法的,会抛 ...

  5. 重塑云上的 Java 语言

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 Photo @  Toa Heftiba 文 |郁磊 音乐无国界, ...

  6. 四川大学java试题_四川大学2013年计算机(软件)学院Java语言程序设计期末考试试题B卷...

    四川大学期末考试试题(闭卷) (2013 -2014学年第1学期) 课程号:课程名称: Java语言程序设计(B 卷)任课教师: 适用专业年级:学号:姓名: 一.单项选择题(本大题共20小题,每小题2 ...

  7. “坑爹”排行榜:Java语言最违反常识的功能点TOP 10

    来自:互联网全栈架构 作为一门面向对象的编程语言,Java凭借其简单易用.功能强大的特点受到了广大编程爱好者的青睐,伴随着开源社区的推波助澜,Java语言更是席卷全球,势不可挡,在世界各地都有Java ...

  8. Java语言中的生僻知识

    最近有一首名叫<生僻字>的流行歌曲火遍大江南北,创作者给佶屈聱牙的生僻字,配上了优美明快的旋律,竟然让歌曲变得琅琅上口.悦耳动听起来,平时不太常见的拒人于千里之外的这些汉字也不再那么陌生, ...

  9. java语言仅支持单重继承_java语言程序设计基础篇习题_复习题_第十一章

    java语言程序设计基础篇习题_复习题_第十一章 11.1 下面说法是真是假?一个子类是父类的子集. 11.2 使用什么关键字来定义一个子类 11.3 什么是单一继承?什么是多重继承?java支持多重 ...

最新文章

  1. System Center 2012 R2 CM系列之Configuration Manager介绍
  2. Eclipse常用设置
  3. 曾今的代码系列——获取当天最大流水号存储过程
  4. java实现二进制转十六进制
  5. COG、XR、X5R、Y5V电容器分类
  6. php 获取文件给用户下载,php 下载文件/直接下载数据内容
  7. LeetCode 910. 最小差值 II(贪心)
  8. k近邻算法(KNN)-分类算法
  9. 使用电脑adb给Essential Phone刷机 —(官方篇)
  10. 监听滚动条和浏览器大小变化
  11. day4-Python学习笔记(七)函数与模块
  12. [HTTP协议] 基础知识
  13. 深度学习大厂前端项目开发全流程全流程
  14. 区块链技术对大数据有哪些影响
  15. 微星主板黑苹果_组装电脑哪个主板好?如何选择电脑主板?2020年电脑主板推荐及分析。...
  16. 复制iPhone端百度网盘下载好的视频到电脑(Mac / Windows)- iOS 12.4
  17. hbase数据库详解
  18. 为什么是“深度”学习而不是宽度?
  19. word里双横线怎么打_word怎么加双下划线
  20. GBT 31000-2015 社会治安综合治理基础数据规范 数据项 编码

热门文章

  1. AMOS实验——方差估计与假设检验
  2. 记账本设置密码,账目不被修改
  3. 技术更高,设计更远:华为全屋智能设计大赛的审美之跃
  4. MPU6500驱动调试笔记(STM32F427+SPI2)
  5. 树莓派驱动6轴传感器MPU6500与SPI初体验(二)
  6. 浅谈python的特点
  7. 06-图6. 公路村村通(30)
  8. 初次办流量卡,怎么才能区分是不是物联卡?
  9. wps 模拟分析 规划求解_WPS表格怎么进行规划求解运算?
  10. Navicat使用pgSQL报错不能建表