Dijkstra算法实现(java)
一、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)相关推荐
- 牛客网 最短路 Floyd算法 Dijkstra算法 Java大数
链接:https://www.nowcoder.com/questionTerminal/a29d0b5eb46b4b90bfa22aa98cf5ff17 来源:牛客网 最短路径 热度指数:2992 ...
- 【数据结构】图(最短路径Dijkstra算法)的JAVA代码实现
最短路径的概念 最短路径的问题是比较典型的应用问题.在图中,确定了起始点和终点之后,一般情况下都可以有很多条路径来连接两者.而边或弧的权值最小的那一条路径就称为两点之间的最短路径,路径上的第一个顶点为 ...
- 【路径规划】Dijkstra算法——超详细原理图解
Dijkstra算法详解 1. Dijkstra算法原理 1.1. 有向图的Dijkstra算法 1.2. 无向图和栅格网络的拓展 1.2.1. 无向图 1.2.2. 栅格网络 2. Di ...
- Dijkstra算法(最小路)
在图论中的一个经典求最短路的算法,基本上,所有的数据结构的书籍都会有这个算法,这算法有一个特性,我要求一个点到另一个点的最短距离,这个算法不仅给出这个最短距离还有很多"副产品",也 ...
- 解决最短路径的Dijkstra算法详解,附加Java代码
1. 最短路径问题 最短路径问题是生活中经常碰到的一类问题,如机器人路径规划,数学竞赛以及真实的工程施工问题:甚至是我们程序员笔试必刷算法题.其实问题很简单,就是有很多个节点,我们要计算出一个初始点到 ...
- 贪婪算法在求解最短路径中的应用(JAVA)--Dijkstra算法
最短路径问题最经典的算法就是Dijkstra算法,虽然不如Floyd算法能够求全源的最短路径,但是在效率上明显强于Floyd算法. 想了解Floyd算法的读者可以参考动态规划在求解全源最短路径中的应用 ...
- java数据结构和算法——迪杰斯特拉(Dijkstra)算法
目录 一.迪杰斯特拉(Dijkstra)算法介绍 二.迪杰斯特拉(Dijkstra)算法过程 三.迪杰斯特拉(Dijkstra)算法--应用场景(最短路径问题) 四.迪杰斯特拉(Dijkstra)算法 ...
- Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法
1.Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法 1.1 迪杰斯特拉(Dijkstra)算法 1.1.1 迪杰斯特拉(Dijkstra)算法介绍 迪杰斯特拉(Dijkstra ...
- java实现迪杰斯特拉(Dijkstra)算法求解最短路问题
迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的.是寻找从一个顶点到其余各顶点的最短路径算法,可用来解决最短路径问题. 迪杰斯特拉算法采用贪心算法的策略,将所有顶点分 ...
最新文章
- CMake学习(一)
- 小程序判断屏幕是长屏还是短屏手机,iPhone X 类型还是 iPhone 6类型
- 芯片巨人也要搞医疗?
- opeansea, nft, trend
- 一个程序设计试题:读取2维字符数组,判断出表示的数字
- 【Makefile由浅入深完全学习记录4】变量和不同的赋值方式
- 六石管理学:头目们为什么要忽略产品质量
- 报 刊 集 锦(转载)
- cpu超线程优缺点_CPU有无超线程重要吗?i7 10700K与9700K对比测试
- 项目xx方案文档格式规范模板
- U-net网络框架 学习笔记
- excel单元格斜线_最实用的8个Excel操作技巧,1分钟学会!
- tit-al00 android 6,华为TIT-AL00入网 MTK6735四核全网通手机
- 现代数字信号处理——AR模型
- php 中英文查询字数,php统计中英文混合的文章字数
- c 抓取ajax异步数据,用requests.post提交表单抓取异步ajax信息失败
- DBeaver修改默认存储sql文件的位置
- 华为面试100题:java开发工程师(中)
- 用python创建的神经网络--mnist手写数字识别率达到98%
- c语言中sor函数,用C语言实现SOR方法.doc