数据结构迪杰斯特拉Dijkstra算法详解及其Java实现


本文编写参照此文章: Dijkstra算法图文详解.

算法概念

Dijkstra算法的目标是计算出有向图中,某一点到其他点之间的最短距离,使用的是贪心算法的思想

算法过程

数据元素(本文使用的数组元素都从下标1开始使用,不使用下标0):
map:二维数组,有向图
distance:一维数组,distance[i]为从起点到结点i的最小距离
visited:一维数组,visited[i]为结点i是否访问过

每一次都从distance中选择最近的那一个可访问且未访问过的结点,令index为该结点下标,根据有向图map,从这个结点查找他能访问到的所有结点,查看distance[index] + map[index][j]与distance[j]的关系,如果更小则代表寻找到一条更短的路径,令distance[j] = istance[index] + map[index][j]

直接看实例:
有向图map如下
只有6个结点的有向图
初始的distance数组,每一个元素都是Integer.MAXVALUE
初始的vistited数组,每一个元素都是false

假设要寻找结点1 到其他结点之间的最短距离
在正式开始之前,设置起点的distance为0,即distance[1] = 0

首先从结点1开始,minDistance = distance[1] = 0,可访问的结点为结点2和结点
1到2的距离为0+1,小于distane[2],distane[2]=1
1到3的距离为0+12,小于distance[3],distane[3]=12

此时distance数组内容为:

 0, 		1, 		2, 		3,		4, 			5,		 	6
[2^31-1, 	0, 		1, 		12,		2^31-1, 	2^31-1, 	2^31-1]

此时结点1被标记为已访问,不能再使用结点1,排除结点1后,distance最小的结点为结点2,所以这次使用结点2

minDistance = distance[2] = 1,可访问的结点为结点3和结点4
2到3的距离为9,1 + 9小于distane[3],distane[2]=10
2到4的距离为3,1 + 3小于distance[4],distane[4]=4

此时distance数组内容为:

 0, 		1, 		2, 		3,		4, 		5,		 	6
[2^31-1, 	0, 		1, 		10,		4, 		2^31-1, 	2^31-1]

此时结点2被标记为已访问,不能再使用结点1、结点2,排除这两个结点后,distance最小的结点为结点4,所以这次使用结点4

minDistance = distance[4] = 4,可访问的结点为结点3、结点5、结点6
4到3的距离为4,4 + 4小于distane[3],distane[3]=8
4到5的距离为13,4 + 13小于distance[5],distane[5]=17
4到6的距离为15,4 + 15小于distance[6],distane[6]=19

此时distance数组内容为:

 0, 		1, 		2, 		3,		4, 		5,	 	6
[2^31-1, 	0, 		1, 		8,		4, 		17, 	19]

此时结点4被标记为已访问,不能再使用结点1、结点2、结点4,排除这三个结点后,distance最小的结点为结点3,所以这次使用结点3

minDistance = distance[3] = 8,可访问的结点为结点5
3到5的距离为5,8 + 5小于distane[5],distane[5]=13

此时distance数组内容为:

 0, 		1, 		2, 		3,		4, 		5,	 	6
[2^31-1, 	0, 		1, 		8,		4, 		13, 	19]

此时结点3被标记为已访问,不能再使用结点1、结点2、结点3、结点4,排除这四个结点后,distance最小的结点为结点5,所以这次使用结点5

minDistance = distance[5] = 13,可访问的结点为结点6
5到6的距离为4,13 + 4小于distane[6],distane[6]=17

此时distance数组内容为:

 0, 		1, 		2, 		3,		4, 		5,	 	6
[2^31-1, 	0, 		1, 		8,		4, 		13, 	17]

结点5也标记为已访问,此时未访问的结点只剩下结点6,由于结点6在有向图中不能到达其他结点,因此不会对distance造成影响,算法结束。

distance[1]为结点1到结点1的最短距离
distance[2]为结点1到结点2的最短距离

distance[6]为结点1到结点6的最短距离

实现代码(Java)

代码中initResources方法用于初始化数据,dijkstra方法的入参为需要计算的路径起点。

/**
 * @Author: x1aolone
 * @Date: 2020/3/27 14:04
 * 迪杰斯特拉算法,计算有向图从某点到其他点的最短路径
 * 使用贪心算法,每次从dis[i]最小的点开始更新剩余dis[x]的长度
 */
public class Dijkstra {

    static int[][] map;

    static int[] distance;

    static boolean[] visited;

    public static void dijkstra (int beginIndex) {
        int nodeNum = map.length-1;
        distance[beginIndex] = 0;
        // 所有结点都要访问一次,共nodeNum次
        // 第一次从beginIndex的结点开始
        // 然后每次从未访问过、并且可以访问的最近的结点开始
        for (int i = 0; i < nodeNum; i++) {
            int index = beginIndex;// index代表当前结点的下标
            int minDistance = Integer.MAX_VALUE;// minDistance代表起点到当前结点的最短距离
            for (int j = 1; j <= nodeNum; j++) {
                if (distance[j] < minDistance && !visited[j]) {
                    index = j;
                    minDistance = distance[j];
                }
            }

            for (int j = 1; j <= nodeNum; j++) {
                if (map[index][j] != 0 && minDistance + map[index][j] < distance[j]) {
                    distance[j] = minDistance + map[index][j];
                }
            }
            System.err.println(Arrays.toString(distance));
            visited[index] = true;
        }
    }

    public static void initResources () {
        map = new int[7][7];
        map[1][2] = 1;
        map[1][3] = 12;
        map[2][3] = 9;
        map[2][4] = 3;
        map[3][5] = 5;
        map[4][3] = 4;
        map[4][5] = 13;
        map[4][6] = 15;
        map[5][6] = 4;
        distance = new int[7];
        for (int i = 0; i < 7; i ++) distance[i] = Integer.MAX_VALUE;
        visited = new boolean[7];
    }

    public static void main (String[] args) {
        initResources();
        dijkstra(1);
        System.err.println(Arrays.toString(distance));
    }

}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值