迪杰斯特拉(Dijkstra)算法介绍

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

最短路径

最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径,大致可以分为如下几种问题,可无论如何分类问题,其本质思想还是不变的,即,求两点间的最短距离。

a) 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题。

b) 确定终点的最短路径问题 - 与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。

c) 确定起点终点的最短路径问题 - 即已知起点和终点,求两结点之间的最短路径。

d) 全局最短路径问题 - 求图中所有的最短路径。

迪杰斯特拉(Dijkstra)算法概述

如上图,迪杰斯特拉算法的核心思路是:

  1. 指定一个节点,例如我们要计算 ‘A’ 到其他节点的最短路径

  2. 引入三个集合(dis,already_arr,pre_visited),dis集合包含已求出的最短路径的点(以及相应的最短长度),already_arr 记录各个顶点是否被访问过 (1 表示访问过,0 未访问)会动态更新, pre_visited 每个下标对应的值为前一个顶点下标, 会动态更新

  3. 初始化三个集合,already_arr集合初始时 只有当前节点要设置为已访问(即already_arr[index] = 1)

  4. dis集合初始时为 A->A = 0 A->B = 4, A->C = ∞, A->D = 2, A->E = ∞

  5. 从还没访问的节点中找出路径最短的点,加入dis集合,例如 A->D = 2

  6. 更新already_arr 和 pre_visited 集合路径,if ( ‘D 到 B,C,E 的距离’ + ‘AD 距离’ < ‘A 到 B,C,E 的距离’ ) 则更新already_arr 和 pre_visited 集合

  7. 循环执行 4、5 两步骤,直至遍历结束,得到A 到其他节点的最短路径

迪杰斯特拉算法应用场景-最短路径问题

  1. 战争时期,胜利乡有 7 个村庄(A, B, C, D, E, F, G) ,现在有六个邮差,从 G 点出发,需要分别把邮件分别送到A, B, C , D, E, F 六个村庄

  2. 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5 公里

  3. 问:如何计算出 G 村庄到 其它各个村庄的最短距离?

  4. 如果从其它点出发到各个点的最短距离又是多少?

代码实现

public class DijkstraAlgorithm {// 表示不连通public static final int INF = 65535;public static void main(String[] args) {char[] vertexs = {'A','B','C','D','E','F','G'};int[][] matrix = new int[vertexs.length][vertexs.length];matrix[0]= new int[]{INF, 5, 7, INF, INF, INF, 2};matrix[1]= new int[]{5, INF, INF, 9, INF, INF, 3};matrix[2]= new int[]{7, INF, INF, INF, 8, INF, INF};matrix[3]= new int[]{INF, 9, INF, INF, INF, 4, INF};matrix[4]= new int[]{INF, INF, 8, INF, INF, 5, 4};matrix[5]= new int[]{INF, INF, INF, 4, 5, INF, 6};matrix[6]= new int[]{2, 3, INF, INF, 4, 6, INF};// 创建Graph对象Graph graph = new Graph(vertexs, matrix);graph.showGraph();//要开始寻找的顶点下标int index = 6;graph.dijkstra(index);graph.showDijkstra(index);}
}class Graph {private final char[] vertex; // 顶点数组private final int[][] matrix; // 邻接矩阵private VistedVertex vv; // 已访问顶点集合// 构造器public Graph(char[] vertex, int[][] matrix) {this.vertex = vertex;this.matrix = matrix;}// 显示结果public void showDijkstra(int index) {vv.print(index);}// 显示图public void showGraph() {for (int[] link : this.matrix) {System.out.println(Arrays.toString(link));}}// dijkstra 算法public void dijkstra(int index) {vv = new VistedVertex(vertex.length, index);// 更新 index 下标顶点到周围顶点的距离和周围顶点的前驱顶点update(index);for (int j = 1; j < vertex.length; j++) {// 选择并返回新的访问顶点index = vv.updateArr();// 更新 index 下标顶点到周围顶点的距离和周围顶点的前驱顶点update(index);}}// 更新 index 下标顶点到周围顶点的距离和周围顶点的前驱顶点public void update(int index) {int len;for (int i = 0; i < matrix[index].length; i++) {// len 含义是 : 出发顶点到 index 顶点的距离 + 从 index 顶点到 i 顶点的距离的和len = vv.getDis(index) + matrix[index][i];// 如果 i 顶点没有被访问过,并且 len 小于出发顶点到 i 顶点的距离,就需要更新if (!vv.in(i) && len < vv.getDis(i)) {vv.updatePre(i, index);//更新 i 顶点的前驱为 index 顶点vv.updateDis(i, len);//更新出发顶点到 i 顶点的距离}}}
}// 已访问顶点集合
class VistedVertex {// 记录各个顶点是否被访问过 (1 表示访问过,0 未访问)会动态更新public int[] already_arr;// 每个下标对应的值为前一个顶点下标, 会动态更新public int[] pre_visited;// 记录出发顶点到其他所有顶点的距离,比如 G 为出发顶点,就会记录 G 到其它顶点的距离// 会动态更新,求的最短距离就会存放到 dispublic int[] dis;/*** 构造器* @param length 顶点的个数* @param index 出发顶点对应的下标 eg: G -> 6*/public VistedVertex(int length, int index) {this.already_arr = new int[length];this.pre_visited = new int[length];this.dis = new int[length];// 初始化 dis 数组Arrays.fill(dis, DijkstraAlgorithm.INF);// 设置出发顶点已被访问过this.already_arr[index] = 1;// 设置出发顶点的访问距离为 0this.dis[index] = 0;}/***  判断 index 顶点是否被访问过* @param index 顶点对应的下标* @return 若访问过就返回true,否则返回false*/public boolean in(int index) {return already_arr[index] == 1;}/*** 更新出发顶点到 index 顶点之间的距离* @param index 顶点对应的下标* @param len 距离*/public void updateDis(int index, int len) {this.dis[index] = len;}/*** 更新 pre 顶点的前驱为 index 顶点* @param pre 当前前驱顶点对应的下标* @param index 要更新的前驱顶点对应的下标*/public void updatePre(int pre, int index) {this.pre_visited[pre] = index;}// 返回出发顶点到 index 顶点之间的距离public int getDis(int index) {return this.dis[index];}// 继续选择并返回新的访问顶点// 比如这里的 G 完后,就是 A 点作为新的访问顶点(注意不是出发顶点)public int updateArr() {int min = DijkstraAlgorithm.INF;int index = 0;for (int i = 0; i < already_arr.length; i++) {if (already_arr[i] == 0 && dis[i] < min) {min = dis[i];index = i;}}// 更新 index 顶点已被访问过already_arr[index] = 1;return index;}// 打印最后的结果public void print(int index) {System.out.println("\nalready_arr==========================");for (int i : already_arr) {System.out.print(i + " ");}System.out.println("\npre_visited==========================");for (int i : pre_visited) {System.out.print(i + " ");}System.out.println("\ndis==================================");for (int i : dis) {System.out.print(i + " ");}System.out.println();char[] vertexs = {'A','B','C','D','E','F','G'};int count = 0;for (int i : dis) {if (i != DijkstraAlgorithm.INF) {System.out.print(vertexs[index] + "->" + vertexs[count] + "的距离:" + i + "\t");} else {System.out.println("INF");}count++;}}
}

运行结果

从G点开始

从A点开始

从B点开始

:以上大部分内容来源于韩顺平老师的数据结构和算法笔记

DijkstraAlgorithm(迪杰斯特拉算法)相关推荐

  1. 迪杰斯特拉算法(最短路径)

    描述 算法过程 代码实现 package com.atguigu.dijkstra;import com.sun.xml.internal.fastinfoset.algorithm.BooleanE ...

  2. 迪杰斯特拉c++_常用十大算法之 其九·迪杰斯特拉算法【日后详细补充】

    介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 问题-最短路径 ...

  3. 【数据结构与算法】迪杰斯特拉算法的介绍和最短路径问题程序实现

    目录 1. 迪杰斯特拉算法的介绍 2. 迪杰斯特拉算法的原理 3. 最短路径问题介绍 1. 迪杰斯特拉算法的介绍 迪杰斯特拉(Dijkstra)算法是典型求两点之间最短路径算法.它的主要特点是以起始点 ...

  4. 图解迪杰斯特拉算法(最短路径问题)

    文章目录 一.单源最短路径问题 二.迪杰斯特拉算法 2.1 什么是迪杰斯特拉算法 2.2 迪杰斯特拉算法的步骤 2.2.1 基本步骤 2.2.2 图解演示 2.3 迪杰斯特拉算法的代码实现 一.单源最 ...

  5. 常用算法(八)——迪杰斯特拉算法

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

  6. 迪杰斯特拉算法(C语言实现)

    迪杰斯特拉算法(C语言实现) 如上图,求以a为源点到个顶点的最短路劲. #include "stdio.h" #include "stdlib.h" //用一个 ...

  7. C++迪杰斯特拉算法求最短路径

    一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...

  8. 迪杰斯特拉算法——PAT 1003

    本文主要是将我对于我对于迪杰斯特拉算法的理解写出来,同时通过例题来希望能够加深对于算法的理解,其中有错误的地方希望大家指正. 迪杰斯特拉算法 我将这个算法理解成一个局部到整体的算法,这个方法确实越研究 ...

  9. 单源最短路径-Dijkstra(迪杰斯特拉算法)

    迪杰斯特拉算法时间复杂度为O(n^2),其中n为顶点个数. 该算法用于求单源最短路径.并且图中的边不允许带负权值. #include <iostream> using namespace ...

最新文章

  1. Linux 下 Redis 安装详解
  2. python es 数据库_Python将json文件写入ES数据库的方法
  3. java导出oracle到excel_java实现将oracle表中的数据导出到excel表里
  4. 指定输出路径_新手Python必须知道的文件路径和变量命名技巧
  5. 理解Prefix.pch文件
  6. vim中跳到第一行和最后一行
  7. ASP.NET Core 中文文档 第三章 原理(2)中间件
  8. 如何实现微服务架构下的分布式事务?
  9. element 搜索匹配_如何在Element-ui中实现一个远程搜索功能
  10. 《深入浅出DPDK》学习思维导图
  11. 【Linux】Linux的常用远程工具
  12. F5补丁修复及几点命令
  13. 解决IIS数据库连接出错方法
  14. 远程连接IBM MQ 7.5的“AMQ4036”错误解决
  15. CentOS6.x 下 LNMP环境搭建(二、安装 Nginx)
  16. eclipse maven 打war包的几种方式
  17. 点云sift matlab,点云配准SIFT算法
  18. 互联网日报 | 瑞幸咖啡内部调查基本完成;12306官方支付宝小程序上线;华为openGauss正式开源...
  19. 烟雾检测传感器实验-传感器原理及应用实验
  20. Toast调整显示位置

热门文章

  1. ES6中...省略号的意思
  2. a++与++a同a--与--a代码拆分
  3. PDF生成技巧:怎么把其他格式转换成PDF文件?
  4. 网传美团今年应届生年薪 35w+,严重倒挂老员工,为什么互联网大厂校招的薪资一年比一年高?...
  5. pmp考试多长时间出成绩?
  6. NEON Intrinsics 练习题
  7. Java 读取 Excel 模板,将数据填入Excel表格,后转换为PDF文件(实用)
  8. 抖音的服务器到底啥配置?
  9. NavMesh基础使用
  10. 用C语言做了一个外卖管理系统