【最短路径算法】迪杰斯特拉算法

目录

应用场景

图的存储结构 —— 邻接矩阵

算法思想

举例子说明具体思路 

伪代码

算法实现


应用场景

  1. 这个算法用于解决图中单源最短路径问题(单源节点是指给定源节点)求图中其它节点到此源节点的最短路径。给定源节点a,求节点b到a的最短距离。

  2. 对带权图(有无向均可)寻找最短路径

  3. 对不含负权的图来讲,是目前最快的单源最短路径算法

  4. 时间复杂度O(n2)

 

图的存储结构 —— 邻接矩阵

【最短路径算法】迪杰斯特拉算法_第1张图片

 

二维数组lines[I][j]表示顶点i到顶点j的路径权重,不能到达的设置为无穷大

 

算法思想

 

Dijkstra的大致思想就是:

  1. 根据初始点,挨个的把离初始点最近的点一个一个找到并加入集合,集合中所有的点的d[i]都是该点到初始点最短路径长度

  2. 由于后加入的点是根据集合S中的点为基础拓展的,所以也能找到最短路径

 

 

用到的变量除了记录路径的lines数组之外,需要一个额外的集合point保存已经找到最短路径的顶点和距离(初始化时只有起点)

我们这里用一个point[i]数组来记录

例如对于某个顶点i,如果point[i]为xx则表示这个顶点在集合中并且距离为xx,如果point[i]为无穷大则表示这个顶点不在集合中

 

先选定某一个顶点,再推敲到达该顶点的距离问题

  1. 从lines[s]数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到集合point中,此时选定一个顶点K

  2. 查看新加入的顶点K是否可以到达其他顶点以比源点直接到达更短,如果是,那么就替换这些顶点在lines[k]中的值

  3. 重复上述动作,直到point中包含了图的所有顶点。

 

举例子说明具体思路 

【最短路径算法】迪杰斯特拉算法_第2张图片

起点1

  1. 源点为1

    1. 从lines[1]中寻找最短的路径,确定顶点为2,point[2] = 7

    2. 没有其他路径

    3. 最终point[2] = 7,新的源点为2

  2. 源点为2

    1. 寻找lines[2]中的最小值,确定顶点为顶点3,路径为 point[3] = point[2]+min(lines[2][3] = 17

    2. 查看顶点3是否可以通过集合内的其他点(1)到达 point[3] = min (point[k] + lines[k][3]) = 9

    3. point[3] = 9,新的源点为3

  3. 源点为3

    1. 寻找lines[3]中最小值为2,确定顶点为6,point[6] = point[3] + lines[3][6] = 11

    2. 查看顶点6是否可以通过集合内的其他点(1,2)到达 point[6] = min (point[k] + lines[k][6]) = 14

    3. point[6] = 11,新的源点为6

  4. 源点为6

    1. 确定顶点为5...

    2. ….

    3. ...

  5. 源点为5

    1. 确定顶点为4

    2. ...

    3. ...

  6. 完成

 

伪代码

for(顶点0 : 所有顶点) {

     

    1 初始化points



    2 循环顶点次数-1次(这里一定要减一,N个顶点找N-1次,如果不减一,最后一次找不到新的end会出错)



        2.1for循环寻找从start开始最近的点 end(确定顶点),当然这个顶点是未在集合中的,所以有points[k] == Integer.MAX_VALUE限制


        2.2更新points数组中其他点到end的值(确定值)



        2.3 start=end,设定新的源点为start

}

 

算法实现

 

应用题目:

【最短路径算法】迪杰斯特拉算法_第3张图片

 

说明:

  1. lines中不可到达设置的0

  2. 顶点为0-N,起点为0

private static void dijkstra(int[][] lines,int[] points) {

    // 1 初始化points

    for(int i = 1; i < points.length; i++) {

        points[i] = Integer.MAX_VALUE;

    }

    // 2 算法流程

    int start = 0; //从起点0开始

    int end = 0;

    for (int j = 0; j < points.length - 1; j++) {

        int min = Integer.MAX_VALUE;

        // 2.1 for循环寻找从start开始最近的点 end(确定顶点)

        for (int k = 0; k < points.length; k++) {

            if (points[k] == Integer.MAX_VALUE && lines[start][k] != 0 && lines[start][k] < min) {

                min = lines[start][k];

                end = k;

            }

        }

        points[end] = points[start] + min;

        // 2.2更新points数组中其他点到end的值(确定值)

        for (int k = 0; k < points.length; k++) {

            points[end] = lines[k][end] != 0 ? Math.min(points[end],(points[k] + lines[k][end])) : points[end];

        }

        // 2.3end作为新的源点

        start = end;

    }

}

 

 

 

你可能感兴趣的:(数据结构与算法,算法)