一、Dijkstra算法介绍

  Dijkstra(迪杰斯特拉)算法是求解单源最短路径的经典算法,其原理也是基于贪心策略的。

二、Dijkstra算法原理

  Dijkstra算法设置一个集合SSS记录已求得的最短路径的顶点,初始时把源点v0v_{0}v0​放入SSS,集合SSS每并入一个新顶点viv_{i}vi​,都要修改源点v0v_{0}v0​到集合V−SV-SV−S中顶点当前的最短路径长度值。
  在构造的过程中还设置了两个辅助数组:

(1)dist[]:记录从源点v0v_{0}v0​到其他各顶点当前的最短路径长度,它的初态为:若从v0v_{0}v0​到viv_{i}vi​有弧,则dist[i]为弧上的权值;否则置dist[i]为∞∞∞。
(2)path[]: path[i]表示从源点到顶点i之间的最短路径的前驱结点。在算法结束时,可根据其值追溯得到源点v0v_{0}v0​到顶点viv_{i}vi​的最短路径。

  假设从顶点0出发,即v0=0v_{0}=0v0​=0,集合SSS最初只包含顶点0,邻接矩阵arcs表示带权有向图,若不存在有向边<i,j>,则arcs [i][j]arcs[i][j]表示有向边<i,j>的权值∞∞∞。
  Dijkstra算法的步骤如下(不考虑对path[]的操作):

1)初始化:集合S初始为{0},dist[]的初始值dist[i]=arcs[0][i];i=1,2,…,n-1
2)从顶点集合V-S中选出vjv_{j}vj​,满足dist[j]=Min {dist[i]},vi∈V−Sv_{i} \in V-Svi​∈V−S,vjv_{j}vj​就是当前求得的一条从v0v_{0}v0​出发的最短路径的终点,令S=S∪jS=S\cup {j}S=S∪j。
3)修改从v0v_{0}v0​出发到集合V-S上任一顶点vkv_{k}vk​可达的最短路径长度:若dist[j]+arcs[j][k]<dist[k],则更新dist [k]=dist[j]+arcs[j][k]
4)重复2)~3)操作共n-1次,直到所有的顶点都包含在S中。

步骤3),每当一个顶点加入S后,可能需要修改源点v0v_{0}v0​到集合V-S中可达顶点当前的最短路径长度,下面举一简单例子证明。如下图所示,源点为v0v_{0}v0​,初始时S={v0v_{0}v0​},dist[1]=4,dist[2]=8,当将v1v_{1}v1​并入集合S后,dist[2]需要更新为6。

三、Dijkstra算法示例

顶点 第1轮 第2轮 第3轮 第4轮
2 10(v1v_{1}v1​->v2v_{2}v2​) 8(v1v_{1}v1​->v5v_{5}v5​->v2v_{2}v2​) 8(v1v_{1}v1​->v5v_{5}v5​->v2v_{2}v2​)
3 ∞∞∞ 14(v1v_{1}v1​->v5v_{5}v5​->v3v_{3}v3​) 13(v1v_{1}v1​->v5v_{5}v5​->v4v_{4}v4​->v3v_{3}v3​) 9(v1v_{1}v1​->v5v_{5}v5​->v2v_{2}v2​->v3v_{3}v3​)
4 ∞∞∞ 7(v1v_{1}v1​->v5v_{5}v5​->v4v_{4}v4​)
5 5(v1v_{1}v1​->v5v_{5}v5​)
集合S {1,5} {1,5,4} {1,5,4,2} {1,5,4,2,3}

  从顶点1开始,每次将最短路径的顶点加入集合,根据集合中已有是的顶点,寻找到各个顶点的最短路径。

四、代码实现

package com.haiyang.algorithm.dijkstra;import com.sun.corba.se.impl.orbutil.graph.Graph;import java.util.Arrays;/*** @author haiYang* @create 2022-02-03 10:33*/
public class DijkstraAlgorithm {public static void main(String[] args) {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};//邻接矩阵int[][] matrix = new int[vertex.length][vertex.length];final int N = 65535;// 表示不可以连接/*                    1  2  3  4   5   */matrix[0] = new int[]{N, 10, N, N, 5};/*1*/matrix[1] = new int[]{N, N, 1, N, 2};/*2*/matrix[2] = new int[]{N, N, N, 4, N};/*3*/matrix[3] = new int[]{7, N, 6, N, N};/*4*/matrix[4] = new int[]{N, 3, 9, 2, N};/*5*///创建 Graph对象DGraph graph = new DGraph(vertex, matrix);//测试, 看看图的邻接矩阵是否okgraph.showGraph();//测试迪杰斯特拉算法graph.dijkstra(0);graph.showDijkstra('A', 'C');}}//已访问顶点集合
class VisitedVertex {//记录各个顶点是否访问,1表示访问过,0表示未访问过public int[] alreadyVertex;//表示从源点到顶点i之间的最短路径的前驱结点public int[] path;//记录从源点到其他各个顶点当前的最短路径长度public int[] dist;/*** 构造器** @param vertexNum   顶点数目* @param vertexIndex 顶点索引(顶点数组对应的下标)*/public VisitedVertex(int vertexNum, int vertexIndex) {this.alreadyVertex = new int[vertexNum];this.path = new int[vertexNum];this.dist = new int[vertexNum];//初始化dist数组,顶点i到其他顶点的距离初始为65536,到自己的距离初始为0。Arrays.fill(dist, 65535);dist[vertexIndex] = 0;//初始顶点已访问this.alreadyVertex[vertexIndex] = 1;}/*** 判断该顶点是否已经访问过** @param vertexIndex 顶点索引* @return*/public boolean isVisited(int vertexIndex) {return alreadyVertex[vertexIndex] == 1;}/*** 更新源点到目标顶点的最短路径长度** @param objectiveVertexIndex  目标顶点索引* @param objectiveVertexLength 目标顶点长度*/public void updateDist(int objectiveVertexIndex, int objectiveVertexLength) {dist[objectiveVertexIndex] = objectiveVertexLength;}/*** 更新源点到该顶点最短路径下,该顶点的前驱顶点** @param preVertexIndex 前驱顶点* @param VertexIndex    该顶点*/public void updatePath(int VertexIndex, int preVertexIndex) {path[VertexIndex] = preVertexIndex;}/*** 返回源点到该顶点的上一次更新的最短路径* 用于判断此次是否更新最短路径长度** @param vertexIndex* @return*/public int getDist(int vertexIndex) {return dist[vertexIndex];}/*** 寻找与源点之间最短距离且未访问顶点的索引** @return*/public int updateArr() {int min = 65536, index = 0;for (int i = 0; i < alreadyVertex.length; i++) {if (alreadyVertex[i] == 0 && dist[i] < min) {min = dist[i];index = i;}}alreadyVertex[index] = 1;return index;}public void show(char begin, char end) {System.out.println("===================");int beginIndex = 0;int endIndex = 0;char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};for (int i = 0; i < vertex.length; i++) {if (vertex[i] == begin) {beginIndex = i;}if (vertex[i] == end) {endIndex = i;}}System.out.println(begin + " -> " + end + "的最短距离为:" + dist[endIndex]);System.out.print(begin + " -> " + end + "的最短路径为:");showPath(beginIndex, endIndex);System.out.println(vertex[endIndex]);}/*** 通过递归遍历先驱数组path返回最短路径** @param beginIndex* @param endIndex*/private void showPath(int beginIndex, int endIndex) {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};if (path[endIndex] == beginIndex) {System.out.print(vertex[beginIndex] + " -> ");return;} else {showPath(beginIndex, path[endIndex]);}System.out.print(vertex[path[endIndex]] + " -> ");}}class DGraph {private char[] vertex;//顶点数组private int[][] arcs;//邻接矩阵private VisitedVertex visitedVertex;public DGraph(char[] vertex, int[][] arcs) {this.vertex = vertex;this.arcs = arcs;}public void showGraph() {for (int[] link : arcs) {System.out.println(Arrays.toString(link));}}/*** dijkstra算法** @param index 出发顶点的下标*/public void dijkstra(int index) {visitedVertex = new VisitedVertex(vertex.length, index);update(index);for (int i = 1; i < vertex.length; i++) {index = visitedVertex.updateArr();update(index);}}//更新index下标顶点到周围顶点的距离和周围顶点的前驱顶点public void update(int index) {int len = 0;//根据邻接矩阵找到邻接顶点for (int i = 0; i < arcs[index].length; i++) {//从出发顶点到index顶点的距离+ 从index顶点到i顶点的距离的和len = visitedVertex.getDist(index) + arcs[index][i];if (!visitedVertex.isVisited(i) && len < visitedVertex.getDist(i)) {visitedVertex.updatePath(i, index);//更新前驱顶点visitedVertex.updateDist(i, len); //更新最短距离}}}public void showDijkstra(char begin, char end) {visitedVertex.show(begin, end);}}

Dijkstra算法实现(java)相关推荐

  1. 牛客网 最短路 Floyd算法 Dijkstra算法 Java大数

    链接:https://www.nowcoder.com/questionTerminal/a29d0b5eb46b4b90bfa22aa98cf5ff17 来源:牛客网 最短路径 热度指数:2992 ...

  2. 【数据结构】图(最短路径Dijkstra算法)的JAVA代码实现

    最短路径的概念 最短路径的问题是比较典型的应用问题.在图中,确定了起始点和终点之后,一般情况下都可以有很多条路径来连接两者.而边或弧的权值最小的那一条路径就称为两点之间的最短路径,路径上的第一个顶点为 ...

  3. 【路径规划】Dijkstra算法——超详细原理图解

    Dijkstra算法详解 1. Dijkstra算法原理  1.1. 有向图的Dijkstra算法  1.2. 无向图和栅格网络的拓展   1.2.1. 无向图   1.2.2. 栅格网络 2. Di ...

  4. Dijkstra算法(最小路)

    在图论中的一个经典求最短路的算法,基本上,所有的数据结构的书籍都会有这个算法,这算法有一个特性,我要求一个点到另一个点的最短距离,这个算法不仅给出这个最短距离还有很多"副产品",也 ...

  5. 解决最短路径的Dijkstra算法详解,附加Java代码

    1. 最短路径问题 最短路径问题是生活中经常碰到的一类问题,如机器人路径规划,数学竞赛以及真实的工程施工问题:甚至是我们程序员笔试必刷算法题.其实问题很简单,就是有很多个节点,我们要计算出一个初始点到 ...

  6. 贪婪算法在求解最短路径中的应用(JAVA)--Dijkstra算法

    最短路径问题最经典的算法就是Dijkstra算法,虽然不如Floyd算法能够求全源的最短路径,但是在效率上明显强于Floyd算法. 想了解Floyd算法的读者可以参考动态规划在求解全源最短路径中的应用 ...

  7. java数据结构和算法——迪杰斯特拉(Dijkstra)算法

    目录 一.迪杰斯特拉(Dijkstra)算法介绍 二.迪杰斯特拉(Dijkstra)算法过程 三.迪杰斯特拉(Dijkstra)算法--应用场景(最短路径问题) 四.迪杰斯特拉(Dijkstra)算法 ...

  8. Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法

    1.Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法 1.1 迪杰斯特拉(Dijkstra)算法 1.1.1 迪杰斯特拉(Dijkstra)算法介绍 迪杰斯特拉(Dijkstra ...

  9. java实现迪杰斯特拉(Dijkstra)算法求解最短路问题

    迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的.是寻找从一个顶点到其余各顶点的最短路径算法,可用来解决最短路径问题. 迪杰斯特拉算法采用贪心算法的策略,将所有顶点分 ...

最新文章

  1. CMake学习(一)
  2. 小程序判断屏幕是长屏还是短屏手机,iPhone X 类型还是 iPhone 6类型
  3. 芯片巨人也要搞医疗?
  4. opeansea, nft, trend
  5. 一个程序设计试题:读取2维字符数组,判断出表示的数字
  6. 【Makefile由浅入深完全学习记录4】变量和不同的赋值方式
  7. 六石管理学:头目们为什么要忽略产品质量
  8. 报 刊 集 锦(转载)
  9. cpu超线程优缺点_CPU有无超线程重要吗?i7 10700K与9700K对比测试
  10. 项目xx方案文档格式规范模板
  11. U-net网络框架 学习笔记
  12. excel单元格斜线_最实用的8个Excel操作技巧,1分钟学会!
  13. tit-al00 android 6,华为TIT-AL00入网 MTK6735四核全网通手机
  14. 现代数字信号处理——AR模型
  15. php 中英文查询字数,php统计中英文混合的文章字数
  16. c 抓取ajax异步数据,用requests.post提交表单抓取异步ajax信息失败
  17. DBeaver修改默认存储sql文件的位置
  18. 华为面试100题:java开发工程师(中)
  19. 用python创建的神经网络--mnist手写数字识别率达到98%
  20. c语言中sor函数,用C语言实现SOR方法.doc

热门文章

  1. 路由器网口1一直闪烁正常吗_为什么就是连不上网!网口1一会闪的特别快,网口2闪烁正常!为啥电脑也连不上网...
  2. JAVA经典面试题93道
  3. 大连市新冠疫情 新浪微博评论数据
  4. 高僧与少女的私生子!看懂了,你离成功就不远!
  5. Axes Studio工作室章程
  6. 计算机链接新网络地址,电脑怎么连接新网络
  7. java excel 0没了,解决导出Excel后0丢失的问题
  8. 【LeetCode】91.解码方法
  9. 大语言模型中的涌现现象是不是伪科学?
  10. 当 ChatGPT 比你更会写代码,程序员还能干什么?