图论的灵魂——带你走进迪杰斯特拉算法的世界

简介: 图论的灵魂——带你走进迪杰斯特拉算法的世界

一、引言

从前有一个小小的村庄,在村庄里面有许多的村民,这些村民有一个相同的爱好

他们喜欢每天去不同的人家串门,一起喝喝酒、打打牌(呜呜呜,羡慕了

但最近他们有一个比较烦恼的问题,小A想去小D家,但怎么去才能让路程最短呢?

毕竟,这个村庄每天有无数人来串门,如果能够找到一个路程最短的路线,能为这个村庄提供巨大的帮助

我们的小黄这一天正巧来到这个村庄,利用 最短路 的知识解决了该问题,获得了村民的一致好评

让我们一起看看,最短路 如何解决的该问题

在阅读本文章之前,建议阅读下列文章:

二、什么是最短路

我们把上述的村庄抽象为下列的图:

我们观察一下,从 A 点到 C 点,路线有无数种

  • A - E - C:2 + 4 = 6
  • A - D - C:6 + 1 = 7
  • A - B - C:3 + 10 = 13
  • …省略

我们可以看到,从图上来讲,我们选择 A - E - C 这条路线是最短的

我们怎么通过计算机求出来呢

三、迪杰特斯拉算法

我们还是以这张图为基础

我们要求的目标:A 到 C 的最短距离

1、我们从 A 点开始,记录其路程


d5f46ffabcdb4d9d9a4a4137e53b9dd0.png

对于 A 点来说,所能到达的地方如下:

  • A -> B = 3
  • A -> E = 2
  • A -> D = 6

我们更新表中的值,如下:蓝色代表已经使用完的节点


2、我们从中找出一个路程最短的点:E,分析其能达到的地方

  • E -> B = 7
  • E -> C = 4

我们更新表的值,如下:

这里可能有些读者可能会有两个疑问

  • 第一:路程是怎么样变化的
  • 我们本次求的是 A 点到其他点的最短路径
  • C的路程变成6:求 A 点到 C 点时,路径为:A - E - C,所以路程为:A-> E + E -> C = 2 + 4
  • 第二:为什么E点用完就确定是最短的
  • 我们在进行选择时,始终选择的是当前所有节点中最小的节点
  • 意味着当前我们 A -> E 的长度是小于所有 A 到其他点的距离的

3、我们从中找出一个路程最短的点:B,分析其能达到的地方

  • B -> C = 7

我们更新表的值:


0a9c75bc4ebb4a55bcc878b508984502.png

、我们从中找出一个路程最短的点:D,分析其能达到的地方

  • D -> E = 12
  • D -> C = 1

我们更新表的值:

5、我们从中找出一个路程最短的点:C,分析其能达到的地方

我们更新表的值:

最终我们可以看到,我们 A 点到其他点的最短路径

四、迪杰特斯拉算法代码

  public HashMap<Node, Integer> dijkstra(Node from) {
        // 创建一个点 from 到达其他各位置的 map 映射
        // key:节点,value:路程
        HashMap<Node, Integer> map = new HashMap<>();
        // 将 from 自己到达自己的距离设置为 0
        map.put(from, 0);
        // 当前已经确定的点,便于后续进行筛选
        HashSet<Node> set = new HashSet<>();
        // 找到当前路程最小并且没有被确定的点
        Node minNode = getMinDistanceAndUnselectedNode(map, set);
        while (minNode != null) {
            // 遍历该点的所有边
            for (Edge edge : minNode.edges) {
              // 看一下是否是已经确定的点
                if (!set.contains(edge.to)) {
                    if (map.containsKey(edge.to)) {
                        // 如果该点被访问过
                        // 比较路程大小,看是否需要更新
                        if (edge.weight + map.get(minNode) < map.get(edge.to)) {
                            map.put(edge.to, edge.weight + map.get(minNode));
                        }
                    } else {
                        // 如果该点还没有被访问过
                        map.put(edge.to, edge.weight + map.get(minNode));
                    }
                }
            }
            set.add(minNode);
            minNode = getMinDistanceAndUnselectedNode(map, set);
        }
        return map;
    }
    public Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> map, HashSet<Node> set) {
        Node minNode = null;
        int minValue = Integer.MAX_VALUE;
        for (Node node : map.keySet()) {
            if (!set.contains(node)) {
                if (map.get(node) <= minValue) {
                    minNode = node;
                    minValue = map.get(node);
                }
            }
        }
        return minNode;
    }

不仅包括图的源码,还包括如下内容:

五、总结

简单来说,迪杰特斯拉算法在我们日常生活和业务中都有所存在

比如百度地图、高德地图、美团外卖等,怎么确定两点间的最短距离是关键

当然,看完本篇文章之后,也需要大量的场景去进行练习,不然容易生疏

  • 743. 网络延迟时间【模板题】
  • 当然,我们会发现在每一次寻找 getMinDistanceAndUnselectedNode 浪费了大量的时间,基于堆优化的迪杰斯特拉算法 对此做了优化,有兴趣的读者可以去看看,这里就不再论述了
相关文章
|
7月前
|
机器学习/深度学习 安全 算法
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
|
28天前
|
JSON 算法 数据挖掘
基于图论算法有向图PageRank与无向图Louvain算法构建指令的方式方法 用于支撑qwen agent中的统计相关组件
利用图序列进行数据解读,主要包括节点序列分析、边序列分析以及结合节点和边序列的综合分析。节点序列分析涉及节点度分析(如入度、出度、度中心性)、节点属性分析(如品牌、价格等属性的分布与聚类)、节点标签分析(如不同标签的分布及标签间的关联)。边序列分析则关注边的权重分析(如关联强度)、边的类型分析(如管理、协作等关系)及路径分析(如最短路径计算)。结合节点和边序列的分析,如子图挖掘和图的动态分析,可以帮助深入理解图的结构和功能。例如,通过子图挖掘可以发现具有特定结构的子图,而图的动态分析则能揭示图随时间的变化趋势。这些分析方法结合使用,能够从多个角度全面解读图谱数据,为决策提供有力支持。
|
2月前
|
存储 算法 程序员
迪杰斯特拉(Dijkstra)算法(C/C++)
迪杰斯特拉(Dijkstra)算法(C/C++)
|
5月前
|
算法 Java C++
《经典图论算法》迪杰斯特拉算法(Dijkstra)
这个是求最短路径的迪杰斯特拉算法,另外我还写了50多种《经典图论算法》,每种都使用C++和Java两种语言实现,熟练掌握之后无论是参加蓝桥杯,信奥赛,还是其他比赛,或者是面试,都能轻松应对。
|
7月前
|
算法 Python
Python中实现图论算法
Python中实现图论算法 “【5月更文挑战第20天】”
49 3
|
6月前
|
算法 数据挖掘 定位技术
算法必备数学基础:图论方法由浅入深实践与应用
算法必备数学基础:图论方法由浅入深实践与应用
|
7月前
|
人工智能 算法 BI
【图论】【 割边】【C++算法】1192. 查找集群内的关键连接
【图论】【 割边】【C++算法】1192. 查找集群内的关键连接
|
18天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。
|
24天前
|
机器学习/深度学习 算法 Serverless
基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM
本项目利用鲸鱼优化算法(WOA)优化支持向量机(SVM)参数,针对乳腺癌早期诊断问题,通过MATLAB 2022a实现。核心代码包括参数初始化、目标函数计算、位置更新等步骤,并附有详细中文注释及操作视频。实验结果显示,WOA-SVM在提高分类精度和泛化能力方面表现出色,为乳腺癌的早期诊断提供了有效的技术支持。
|
4天前
|
供应链 算法 调度
排队算法的matlab仿真,带GUI界面
该程序使用MATLAB 2022A版本实现排队算法的仿真,并带有GUI界面。程序支持单队列单服务台、单队列多服务台和多队列多服务台三种排队方式。核心函数`func_mms2`通过模拟到达时间和服务时间,计算阻塞率和利用率。排队论研究系统中顾客和服务台的交互行为,广泛应用于通信网络、生产调度和服务行业等领域,旨在优化系统性能,减少等待时间,提高资源利用率。