韩顺平迪杰斯特拉最短路径问题

老韩, 这一讲我确实听不懂你在讲什么, 所以我去b站搜了别人的思路, 并且实现了一下

去掉主方法和图类, 只需要两个方法就能搞定, 不过都比较长就是了

具体思路比较复杂, 主要就是利用三个数组, 其中访问数组和距离数组是最重要的, 他们要配合使用, 前驱数组主要是用来记录结果的.

dist数组是干嘛的, 它更新的四个条件是什么, 这两个问题搞懂就ok了,

package org.example._28迪杰斯特拉最短路径问题;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class DijkstraDemo {
    public static void main(String[] args) {
        char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int[][] matrix = new int[vertex.length][vertex.length];
        final int INF = Integer.MAX_VALUE;
        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(vertex, matrix);
        //测试, 看看图的邻接矩阵是否ok
        graph.showGraph();

        DijkstraDemo dijkstraDemo = new DijkstraDemo();
        dijkstraDemo.dijkstra(graph, 0); //第二个参数是最初出发点的下标
    }

    public void dijkstra(Graph graph, int src) {
        boolean[] visited = new boolean[graph.getVertex().length]; //visited存储的是顶点是否被访问
        int[] pre = new int[graph.getVertex().length]; //pre存储的是目标点的前驱点
        int[] dist = new int[graph.getVertex().length]; //dist存储的是最初出发点到当前出发点的距离
        final int INF = Integer.MAX_VALUE;

        Arrays.fill(pre, -1); //前驱点全设置成-1,因为0要代表第一个顶点
        Arrays.fill(dist, INF); //最初出发点到所有点的距离都设置成INF
        dist[src] = 0; //最初出发点到自己的距离设置成0,使循环能运行下去

        for (int i = 0; i < graph.getVertex().length - 1; i++) { //到最后一个顶点的时候不需要继续往后找了,所以减一
            //从未访问点中,找到与最初出发点距离最小的那个点的下标
            //因为最初出发点的dist设成0了,其他的都是INF,所以一开始找到的肯定是自己,即start最开始会是0,最初出发点被设置成true
            //第二轮i循环开始start就不会是0,其他出发点会被陆续设置成true
            int start = minDistance(graph, dist, visited);
            visited[start] = true; //出发点设为true已访问

            //end的初始值为什么不能置1?因为最初出发点可能是BCD...所以end初值设成0确保任何最初出发点都能和每个其他点进行比较
            for (int end = 0; end < graph.getVertex().length; end++) {
                //更新dist的条件
                if (graph.getMatrix()[start][end] != INF //要求当前出发点到目标点是连通的,保证有"后路"
                        && dist[start] != INF //要求最初出发点到当前出发点的距离不是无穷大,保证有"前路"
                        && visited[end] == false //要求目标点未被访问过,这句可以改成!visited[end]但我感觉理解起来不够直接
                        //要求最初的出发点到当前出发点的距离 + 当前出发点到目标点的距离 < 最初出发点到目标点的距离
                        && dist[start] + graph.getMatrix()[start][end] < dist[end]) {
                    dist[end] = dist[start] + graph.getMatrix()[start][end]; //更新最初出发点到目标点的距离
                    pre[end] = start; //更新前驱点,也是相当于在更新路径
                }
            }
        }
        System.out.println("各点的前驱结点:" + Arrays.toString(pre));
        System.out.println("从出发点到各点的最短距离,0为出发点: [A,B,C,D,E,F,G] -> " + Arrays.toString(dist));
    }

    //找到未访问顶点中dist最小的点作为下一个出发点,永远保证最初出发点到当前出发点的距离最小,很抠门
    private int minDistance(Graph graph, int[] dist, boolean[] visited) {

        //创建一个哈希表把dist和visited对应起来
        HashMap<Integer, Boolean> map = new HashMap<>();
        for (int i = 0; i < dist.length; i++) {
            map.put(dist[i], visited[i]);
        }

        //找到其中value为false的键值对中,值最小的那个key
        int minKey = -1;
        for (Map.Entry<Integer, Boolean> entry : map.entrySet()) {
            if (Boolean.FALSE.equals(entry.getValue())) {
                if (minKey == -1 || entry.getKey() < minKey) { //minKey==-1这个条件让minKey获得初值
                    minKey = entry.getKey();
                }
            }
        }

        //key是dist数组中的值,利用这个key去dist中找到对应的下标
        int targetIndex = -1;
        for (int i = 0; i < dist.length; i++) {
            if (dist[i] == minKey) {
                targetIndex = i;
            }
        }

        return targetIndex;
    }
}


@Data
@AllArgsConstructor
class Graph {
    private char[] vertex; //顶点数组
    private int[][] matrix; //矩阵

    public void showGraph() {
        for (int[] link : matrix) {
            System.out.println(Arrays.toString(link));
        }
    }
}

注释应该是写的比较明白了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值