zoukankan      html  css  js  c++  java
  • 最短路算法之Dijkstra算法通俗解释

    Dijkstra算法


    说明:求解从起点到任意点的最短距离,注意该算法应用于没有负边的图。

    来,看图。

    用邻接矩阵表示

           int[][] m = {
                    {0, 0, 0, 0, 0, 0},
                    {0, 0, 4, 2, 0, 0},
                    {0, 0, 0, 3, 2, 3},
                    {0, 0, 1, 0, 4, 5},
                    {0, 0, 0, 0, 0, 0},
                    {0, 0, 0, 0, 1, 0}};
    

     备注:第一行(从第零行开始)表示A,第一列(从第零列开始)表示A。m[1][2]表示A到B的距离,如果没有相连则赋值为0。

    首先用dist[i]数组表示从起点到该点的距离,比如dist[3]表示起点A到点C的距离。先全部初始化为无穷大,把起点初始化为0,因为自己到自己距离为0。接下来把所有的点的距离放入一个优先队列。步骤:

    遍历直到队列为空:

    在优先队列中删除值(dist[i])最小的点,不过记得保存下来,然后看与其相邻的点的距离,如果相邻的点的距离大于该点距离加上该点到相邻点的距离,则改变相邻的点的距离为该点距离加上该点到相邻点的距离,在优先队列中改变这个相邻的点的距离就好了。

    解释:就是宽度优先搜索的变形,宽度优先搜索是直接从队列取出来就好了,没有优先顺序,而这个是根据该点的距离值(就是从起点到该点的距离)来确定优先出队顺序。

    在这里优先队列实现的方案有四种:数组,二分堆,d堆,Fibonacci堆。复杂度可以自己去分析一下。提示:你可以计算从队列中删除和加入,复杂度分别是多少,就很容易算出来了。在这里说下数组的吧,从数组中删除最小的:o(V),插入:o(1),总:o(v^2)

    来,看下我的代码实现。我是用的map,复杂度与数组实现类似。

    import java.util.*;
    
    public class Main {
    
        public static int deleteMin(Map<Integer, Integer> map) {
            int min = Integer.MAX_VALUE;
            for (int num : map.values()) {
                min = Math.min(min, num);
            }
            int u = 0;
            for (int num : map.keySet()) {
                if (map.get(num) == min) {
                    u = num;
                    break;
                }
            }
            map.remove(u);
            return u;
        }
    
        public static void dijkstra(int[][] m) {
            int n = m.length;
            int[] dist = new int[n + 1];
            int[] pre = new int[n + 1];
            for (int i = 0; i < n; i++) dist[i] = Integer.MAX_VALUE;
            dist[1] = 0;
            pre[1] = 1;
            //点与距离
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 1; i < n; i++) {
                map.put(i, dist[i]);
            }
            while (!map.isEmpty()) {
                int u = deleteMin(map);
                for (int i = 1; i < n; i++) {
                    if (m[u][i] > 0) {
                        if (dist[i] > dist[u] + m[u][i]) {
                            dist[i] = dist[u] + m[u][i];
                            pre[i] = u;
                            map.put(i, dist[i]);
                        }
                    }
                }
            }
            for (int i = 1; i < n; i++) {
                System.out.println("节点1离节点" + i + "距离是:" + dist[i] + ",节点" + i +"的父节点是;" + pre[i]);
            }
        }
    
    
        public static void main(String[] args) {
            int[][] m = {
                    {0, 0, 0, 0, 0, 0},
                    {0, 0, 4, 2, 0, 0},
                    {0, 0, 0, 3, 2, 3},
                    {0, 0, 1, 0, 4, 5},
                    {0, 0, 0, 0, 0, 0},
                    {0, 0, 0, 0, 1, 0}};
            dijkstra(m);
    
        }
    
    }
  • 相关阅读:
    Python基础之内存管理与垃圾回收机制
    Git常用命令
    Git分支操作
    码云配置SSH公钥
    Git基本操作
    Git基本理论
    版本控制
    Python基础之Python语法
    成为一名JAVA高级工程师你需要学什么【转】
    一个java高级工程师的进阶之路【转】
  • 原文地址:https://www.cnblogs.com/ABC-00/p/8082601.html
Copyright © 2011-2022 走看看