图解迪杰斯特拉(Dijkstra)算法(Java语言实现)

概述

感觉迪杰斯特拉好难,才学会的这个算法,所以写下博客加深理解。

Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是带权图中最短路径问题。
Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

Dijkstra算法将图中的节点集分为:
1.最短路径计算完成的节点集S
2.最短路径未计算完成的节点集T

首先选择一个起点,然后每次将从T中挑选“起点->某节点”的路径最短的节点加入S,并更新”起点“经由”某节点”到T中剩余节点的更短距离,直到T中的节点全部加入S中,它在每次都选择一个距离起点最近的节点加入最短路径节点集合。

算法流程

下面我们使用这个图走一遍算法流程,这里我们选择节点A作为起点,计算从起点A到剩余节点的最短路径。在这里插入图片描述
我们使用shortest[ ]、visited[ ]这两个数组,
shortest[index]:存储A到该节点的最短路径,
visited[index]存储v0到该节点的最短路径是否求出。
S为已求出最短路径的节点集,T为未求出最短路径的节点集。起点只允许将S中的节点作为中间节点来计算到达其它节点的最短路径,不允许将T中的节点作为中间节点来计算到达其它节点的最短路径。随着S中节点的增加,起点可达的节点才会增加。
初始状态下,起点只可达B,C,G节点。

1.

将起点A加入S中,对shortest[ ]、visited[ ]进行更新。
在这里插入图片描述

2.

S中现有节点A,起点可达T中的B,C,G节点
节点A->节点B距离为5,节点A->节点C距离为7,节点A->节点G距离为2
按距离从小到大排序,因此选择将节点G加入S中。
更新“起点将节点G作为中间节点到达其它节点的距离”。
在这里插入图片描述

3.

S中现有节点A和节点G,起点可达T中的节点C,B,E,F
A->C=7,A->B=5,A->G->E=6,A->G->F=8
因此选择将节点B加入S中
更新“起点将节点B作为中间节点到达其它节点的距离”
在这里插入图片描述

4.

S中现有节点A,B,G,起点可达T中的节点C、D、E,F
A->C=7,A->G->E=6,A->G->F=8,A->B->D=14
因此选择将节点E加入S中
更新“起点将节点E作为中间节点到达其它节点的距离”
在这里插入图片描述

5.

S中现有节点A、B、E、G,起点可达T中的节点C、D、F,
A->C=7,A->G->F=8,A->B->D=14
因此选择将节点C加入S中
更新“起点将节点C作为中间节点到达其它节点的距离”
在这里插入图片描述

6.

S中现有节点A、B、C、E、G,起点可达T中的节点D、F
A->F=8,A->B->D=14
因此选择将节点F加入S中
更新“源点将节点F作为中间节点到达其它节点的距离。”
在这里插入图片描述

7.

S中现有节点A、B、C、E、F,G
起点可达T中的节点D
A->G->F->D=12
因此选择将节点D加入S中
更新“源点将节点D作为中间节点到达其它节点的距离。”
在这里插入图片描述
结束:到此起点到所有节点的最短路径都求出来了。

JAVA代码实现

package 尚硅谷_数据结构和算法.十种算法.迪杰斯特拉算法;



public class DijstraAlgorithm {
    //不能设置为Integer.MAX_VALUE,否则两个Integer.MAX_VALUE相加会溢出导致出现负权
    public static int M = 100000;
    //定义七个顶点
    private static char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};

    public static void main(String[] args) {

        //初始化邻接矩阵
        int[][] matrix = new int[vertex.length][vertex.length];
        matrix[0] = new int[]{M, 5, 7, M, M, M, 2};
        matrix[1] = new int[]{5, M, M, 9, M, M, 3};
        matrix[2] = new int[]{7, M, M, M, 8, M, M};
        matrix[3] = new int[]{M, 9, M, M, M, 4, M};
        matrix[4] = new int[]{M, M, 8, M, M, 5, 4};
        matrix[5] = new int[]{M, M, M, 4, 5, M, 6};
        matrix[6] = new int[]{2, 3, M, M, 4, 6, M};

        //调用dijstra算法计算最短路径
        dijstra(matrix, 0);
    }

    /**
     * @param matrix:邻接矩阵
     * @param source:起点
     */
    public static void dijstra(int[][] matrix, int source) {
        //最短路径长度
        int[] shortest = new int[matrix.length];
        //判断该点的最短路径是否求出
        int[] visited = new int[matrix.length];
        //存储输出路径
        String[] path = new String[matrix.length];

        //初始化输出路径
        for (int i = 0; i < matrix.length; i++) {
            path[i] = vertex[source] + "->" + vertex[i];
        }

        //初始化起点,将起点放入S
        shortest[source] = 0;
        visited[source] = 1;

        for (int i = 1; i < matrix.length; i++) {       //i从1开始,因为起点已经加入S了
            int min = M;
            int index = -1;

            //找出某节点到起点路径最短
            for (int j = 0; j < matrix.length; j++) {
                //已经求出最短路径的节点不需要再加入计算并判断加入节点后是否存在更短路径
                if (visited[j] == 0 && matrix[source][j] < min) {
                    min = matrix[source][j];
                    index = j;
                }
            }

            //更新最短路径,标记起点到该节点的最短路径已经求出
            shortest[index] = min;
            visited[index] = 1;

            //更新从index跳到其它节点的较短路径
            for (int m = 0; m < matrix.length; m++) {
                if (visited[m] == 0 && matrix[source][index] + matrix[index][m] < matrix[source][m]) {
                    matrix[source][m] = matrix[source][index] + matrix[index][m];
                    path[m] = path[index] + "->" + vertex[m];
                }
            }
        }

        //打印最短路径
        for (int i = 0; i < matrix.length; i++) {
            if (i != source) {
                if (shortest[i] == M) {
                    System.out.println(vertex[source] + "到" + vertex[i] + "不可达");
                } else {
                    System.out.println(vertex[source] + "到" + vertex[i] + "的最短路径为:" + path[i] + ",最短距离是:" + shortest[i]);
                }
            }
        }
    }
}

输出:

AB的最短路径为:A->B,最短距离是:5
AC的最短路径为:A->C,最短距离是:7
AD的最短路径为:A->G->F->D,最短距离是:12
AE的最短路径为:A->G->E,最短距离是:6
AF的最短路径为:A->G->F,最短距离是:8
AG的最短路径为:A->G,最短距离是:2
  • 8
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 的方法有很多种。其中一种是使用邻接矩阵来存储图中的边,然后通过循环更新每个结点的最短路径。代码实现如下: ``` import java.util.*; public class Dijkstra { static final int V=9; int minDistance(int dist[], Boolean sptSet[]) { int min = Integer.MAX_VALUE, min_index=-1; for (int v = 0; v < V; v++) if (sptSet[v] == false && dist[v] <= min) { min = dist[v]; min_index = v; } return min_index; } void printSolution(int dist[], int n) { System.out.println("Vertex Distance from Source"); for (int i = 0; i < V; i++) System.out.println(i+" tt "+dist[i]); } void dijkstra(int graph[][], int src) { int dist[] = new int[V]; Boolean sptSet[] = new Boolean[V]; for (int i = 0; i < V; i++) { dist[i] = Integer.MAX_VALUE; sptSet[i] = false; } dist[src] = 0; for (int count = 0; count < V-1; count++) { int u = minDistance(dist, sptSet); sptSet[u] = true; for (int v = 0; v < V; v++) if (!sptSet[v] && graph[u][v]!=0 && dist[u]+graph[u][v] < dist[v]) dist[v] = dist[u] + graph[u][v]; } printSolution(dist, V); } public static void main (String[] args) { int graph[][] = new int[][]{{0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 14, 10, 0, 2, 0, 0}, {0, 0, 0, 0, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0} }; Dijkstra t = new Dijkstra(); t.dijkstra(graph, 0); } } ``` ### 回答2: 迪杰斯特拉算法是一种用于在加权图中寻找最短路径的算法。使用Java语言实现迪杰斯特拉算法的步骤如下: 1. 创建一个Graph类来表示加权图。图可以使用邻接矩阵或邻接表来表示。 2. 创建一个Edge类来表示图中的边。边包含一个起始顶点、终止顶点和权重。 3. 创建一个Vertex类来表示图中的顶点。顶点包含一个标识符和一个最小权重。 4. 创建一个Dijkstra类来实现迪杰斯特拉算法。 5. 在Dijkstra类中添加一个方法来计算最短路径。这个方法接受一个起始顶点作为参数。 6. 在Dijkstra类中,创建一个集合来存储已访问的顶点。初始化集合,将起始顶点加入集合。 7. 创建一个优先队列来存储未访问的顶点。将起始顶点的最小权重设置为0并加入队列。 8. 创建一个循环,直到优先队列为空。在每次循环中,从队列中取出权重最小的顶点。 9. 对于取出的顶点,遍历其邻接顶点。如果邻接顶点未被访问过,计算其新的最小权重。如果新的最小权重小于原来的最小权重,更新邻接顶点的最小权重并将其加入队列。 10. 循环结束后,可以通过遍历每个顶点的最小权重来找到最短路径。 以上就是使用Java语言实现迪杰斯特拉算法的基本步骤。通过遵循这些步骤,我们可以编写出一个能够找到加权图中最短路径的Dijkstra类。 ### 回答3: 迪杰斯特拉Dijkstra算法是一种解决单源最短路径问题的经典算法。使用Java语言实现迪杰斯特拉算法的步骤如下: 1. 首先,创建一个有向图(Graph)类。该类中包括构造函数和两个方法:addEdge()方法用于添加边,和findShortestPath()方法用于查找最短路径。 2. 在构造函数中,初始化图的顶点数量和邻接矩阵。首先,创建一个二维数组来表示邻接矩阵,初始化值为无穷大。然后,创建一个ArrayList来存储顶点集合。 3. 利用addEdge()方法添加边。这个方法将两个顶点之间的距离存储在邻接矩阵中。 4. 实现findShortestPath()方法。该方法接收两个参数:起始顶点和目标顶点。首先,创建一个一维数组distances,用于存储起始顶点到其他顶点的最短距离。将起始顶点到自身的距离设置为0,其他顶点的距离设置为无穷大。同时,创建一个数组visited,用于记录顶点的访问状态。 5. 在一个循环中,遍历所有顶点,并更新距离数组的值。首先,在未访问的顶点中选择最小距离的顶点,并将其标记为已访问。然后,遍历所有顶点,如果当前顶点未被访问且通过最小距离的顶点可到达当前顶点,则更新最短距离。 6. 最后,打印最短路径。根据最短路径的整理顺序,从目标顶点开始向前查找,直到到达起始顶点。将路径上的顶点依次保存到一个栈中,然后依次出栈打印即可。 以上就是使用Java语言实现迪杰斯特拉算法的大致步骤。通过构建有向图和利用距离数组不断更新最短路径,可以在时间复杂度为O(V^2)的情况下解决单源最短路径问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值