迪杰斯特拉(Dijkstra)算法介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
最短路径
最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径,大致可以分为如下几种问题,可无论如何分类问题,其本质思想还是不变的,即,求两点间的最短距离。
a) 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题。
b) 确定终点的最短路径问题 - 与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
c) 确定起点终点的最短路径问题 - 即已知起点和终点,求两结点之间的最短路径。
d) 全局最短路径问题 - 求图中所有的最短路径。
迪杰斯特拉(Dijkstra)算法概述
如上图,迪杰斯特拉算法的核心思路是:
-
指定一个节点,例如我们要计算 ‘A’ 到其他节点的最短路径
-
引入三个集合(dis,already_arr,pre_visited),dis集合包含已求出的最短路径的点(以及相应的最短长度),already_arr 记录各个顶点是否被访问过 (1 表示访问过,0 未访问)会动态更新, pre_visited 每个下标对应的值为前一个顶点下标, 会动态更新
-
初始化三个集合,already_arr集合初始时 只有当前节点要设置为已访问(即already_arr[index] = 1)
-
dis集合初始时为 A->A = 0 A->B = 4, A->C = ∞, A->D = 2, A->E = ∞
-
从还没访问的节点中找出路径最短的点,加入dis集合,例如 A->D = 2
-
更新already_arr 和 pre_visited 集合路径,if ( ‘D 到 B,C,E 的距离’ + ‘AD 距离’ < ‘A 到 B,C,E 的距离’ ) 则更新already_arr 和 pre_visited 集合
-
循环执行 4、5 两步骤,直至遍历结束,得到A 到其他节点的最短路径
迪杰斯特拉算法应用场景-最短路径问题
-
战争时期,胜利乡有 7 个村庄(A, B, C, D, E, F, G) ,现在有六个邮差,从 G 点出发,需要分别把邮件分别送到A, B, C , D, E, F 六个村庄
-
各个村庄的距离用边线表示(权) ,比如 A – B 距离 5 公里
-
问:如何计算出 G 村庄到 其它各个村庄的最短距离?
-
如果从其它点出发到各个点的最短距离又是多少?
代码实现
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