两点间最短距离 - Dijkstra

news2024/12/23 4:23:43

一、汇总

算法场景说明参考
BFS

无权图的搜索

标准BFS默认搜索一条最短路径

改造后可以输出所有最短路径

https://blog.csdn.net/m0_37145844/article/details/144534202
DFS走迷宫主要利用回溯算法思想,不保证最短路径https://blog.csdn.net/m0_37145844/article/details/144534202
Dijkstra
带权图最短路径的经典解法主要利用贪心思想,其中在u打印路径时候包含递归,回溯等思想本篇讲解

二、Dijkstra 原理

借助java工具类:PriorityQueue 默认内部元素强制根据指定规则进行自然排序的的小顶堆,每次选择下层节点到起点开始算的最小权值的节点作为当前节点,进行向外的下一个层级的探索,最终让所有节点都保存了,此节点从开始节点的最小权重值及其最短路径的父节点。

三、Dijkstra 代码实现-Java版本

有必要讲解一下代码结构:

  1. 内部类的使用
    1. 体现更强的封装性,结构体仅供外部类使用,不对外暴露。
    2. 外部类可以直接调用内部类,简化代码。
    3. 内部类也可以直接使用外部类的成员变量,此例子中暂无体现。
  2. 优先级队列的使用
    1. 比较器的构造。
    2. 因为每次向外层探索时候,都会加入下一层到开始节点权重总和最小的节点,此数据结构强制进行排序,序列化为一个小顶堆。这也是提升此算法性能的关键设计。
    3. 默认为小顶堆。
    4. 距离Map和路径反向记录Map,都体现了算法设计的技巧。
    5. 尤其在打印路径时候,最终用递归思想。
package algo.backtrace.Dijkstra.weiwei;

import java.util.*;

public class Dijkstra {

    class Grap {

        // 带权重的无向图表示,邻接矩阵表示
        Map<Integer, List<Edag>> adjList;

        Grap() {
            adjList = new HashMap<>();
        }

        // 添加边
        public void addEdag(int start, int des, int weight) {
            adjList.putIfAbsent(start, new ArrayList<>());
            adjList.putIfAbsent(des, new ArrayList<>());
            adjList.get(start).add(new Edag(des, weight));
            adjList.get(des).add(new Edag(start, weight));
        }

        // 获取一个顶点的所有边
        public List<Edag> getEdags(int node) {
            return adjList.getOrDefault(node, new ArrayList<>());
        }

        // 获取所有顶点
        public Set<Integer> getAllNodes() {
            return adjList.keySet();
        }
    }

    // 描述边
    class Edag{
        int des;
        int weight;
        Edag(int des, int weight) {
            this.des = des;
            this.weight = weight;
        }
    }

    public Map<Integer, Integer> dijkstra(Grap grap, Integer start) {
        // 定义工具
        PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparing(a -> a[1]));
        Map<Integer, Integer> dist = new HashMap<>();
        Map<Integer, Integer> prev = new HashMap<>();

        // 初始化参数
        for (Integer node : grap.getAllNodes()) {
            dist.put(node, Integer.MAX_VALUE);
            prev.put(node, -1);
        }

        dist.put(start, 0);
        pq.offer(new int[]{start, 0});

        while (!pq.isEmpty()) {
            int[] poll = pq.poll();
            int currNode = poll[0];
            int currWeight = poll[1];

            if (currWeight > dist.get(currNode)) {
                continue;
            }

            for (Edag edag : grap.getEdags(currNode)) {
                int newDist = currWeight + edag.weight;
                if (newDist < dist.get(edag.des)) {
                    dist.put(edag.des, newDist);
                    prev.put(edag.des, currNode);
                    pq.offer(new int[]{edag.des, newDist});
                }
            }
        }

        System.out.println("dist:" + dist);
        System.out.println("prev:" + prev);

        return prev;
    }

    public void printTrace(Map<Integer, Integer> prevMap, int traget, List<Integer> trace) {
        if (prevMap.get(traget) == -1) {
            return;
        }

        traget = prevMap.get(traget);
        printTrace(prevMap, traget, trace);
        trace.add(traget);
    }

    public void main(String[] args) {
        Grap grap = new Grap();
        grap.addEdag(0,1,4);
        grap.addEdag(0,2,1);
        grap.addEdag(1,3,2);
        grap.addEdag(2,3,8);
        grap.addEdag(2,4,3);
        grap.addEdag(4,5,2);
        grap.addEdag(3,5,1);

        Dijkstra dijkstra = new Dijkstra();
        Map<Integer, Integer> prevMap = dijkstra.dijkstra(grap, 0);
        List<Integer> list = new ArrayList<>();
        dijkstra.printTrace(prevMap, 5, list);
        System.out.println(list);
    }
}


// 输出
// dist:{0=0, 1=4, 2=1, 3=6, 4=4, 5=6}
// prev:{0=-1, 1=0, 2=0, 3=1, 4=2, 5=4}
// [0, 2, 4] 瑕疵之处是traget 没有打印出,无伤大雅。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2264047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

thinkphp框架diygw-ui-php进销存出库记录操作

将进销存的出库明细记录存储到数据库中&#xff0c;thinkphp框架diygw-ui-php后台通常涉及以下几个步骤&#xff1a; 数据库表定义 实现我们定义了三张表、一个产品表、出库订单表、出库订单产品明细表 生成API 进入DIY可视化API代码生成器&#xff0c;我们生成这三张表结应…

vertx idea快速使用

目录 1.官网下载项目 2.修改代码 2.1拷贝代码方式 为了能够快速使用&#xff0c;我另外创建一个新的maven项目&#xff0c;将下载项目的src文件和pom文件拷贝到新建的maven项目。 2.2删除.mvn方式 3.更新配置 4.配置application 5.idea启动项目 1.官网下载项目 从vert…

ComE(Community Embedding) -- 基于嵌入的社区检测优化算法

ComE&#xff08;Community Embedding&#xff09;是一种基于嵌入的社区检测优化算法。 它结合了节点嵌入技术与社区划分的目标&#xff0c;能够有效识别网络中的社区结构&#xff0c;并在社区划分过程中捕捉复杂的节点相互作用信息。 算法背景 传统的社区检测方法&#xff0c;…

CSS|14 z-index

z-index z-index表示谁压盖着谁&#xff0c;数值大的会压盖住数值小的。只有定位的元素才有z-index值&#xff0c;只有设置了固定定位、相对定位、绝对定位了的元素&#xff0c;才会拥有z-indexz-index的值是没有单位的&#xff0c;值是一个正整数&#xff0c;默认的z-index值…

重撸设计模式--代理模式

文章目录 定义UML图代理模式主要有以下几种常见类型&#xff1a;代理模式涉及的主要角色有&#xff1a;C 代码示例 定义 代理模式&#xff08;Proxy Pattern&#xff09;属于结构型设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。 通过引入代理对象&am…

vue中验证码的实现方式

在写登录页的时候有的系统会让你也进行一下验证码绘制&#xff0c;那么验证码如何实现的呢&#xff1f;我在写登录页的时候通过将登录框&#xff0c;验证码分开页面来写&#xff0c;最后将它们变成标签来导入到我的样式页面中&#xff0c;这样写不仅方便&#xff0c;更容易修改…

Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器

文章目录 一、SpringWeb概述 二、SpringWeb特点 三、搭建SpringWeb&#xff08;在web项目中&#xff09; 1、导包 2、在web.xml文件中配置统一拦截分发器 DispatcherServlet 3、开启 SpringWEB 注解 4、处理器搭建 四、SpringWeb运行流程 五、SpringWeb组件 1、前端控…

构建MacOS应用小白教程(打包 签名 公证 上架)

打包 在package.json中&#xff0c;dependencies会被打进 Electron 应用的包里&#xff0c;而devDependencies则不会&#xff0c;所以必要的依赖需要放到dependencies中。files中定义自己需要被打进 Electron 包里的文件。以下是一个完整的 mac electron-builder的配置文件。 …

2.4 网络概念(分层、TCP)

网络层与传输层概述 网络层&#xff1a; 抽象概念&#xff1a;网络层是基于 IP 的抽象概念&#xff0c;与数据链路层用 MAC 地址标记设备不同。MAC 地址是一种具体化的概念&#xff0c;绑定于所在的物理网络&#xff0c;而 IP 地址可以是固定的&#xff0c;也可以通过路由动态…

【JetPack】Room数据库笔记

Room数据库笔记 ORM框架&#xff1a;对齐数据库数据结构与面向对象数据结构之间的关系&#xff0c;使开发编程只考虑面向对象不需要考虑数据库的结构 Entity : 数据实体&#xff0c;对应数据库中的表 <完成面向对象与数据库表结构的映射> 注解&#xff1a; 类添加注解…

基于前端技术UniApp和后端技术Node.js的电影购票系统

文章目录 摘要Abstruct第一章 绪论1.1 研究背景与意义1.2 国内外研究现状 第二章 需求分析2.1 功能需求分析2.2 非功能性需求分析 第二章系统设计3.1 系统架构设计3.1.1 总体架构3.1.2 技术选型 3.2 功能架构 第四章 系统实现4.1 用户端系统实现4.1.1 用户认证模块实现4.1.2 电…

大模型微调---Lora微调实战

目录 一、前言二、LoRA实战2.1、下载模型到本地2.2、加载模型与数据集2.3、处理数据2.4、LoRA微调2.5、训练参数配置2.6、开始训练 三、模型评估四、完整训练代码 一、前言 LoRA是一种参数高效的微调技术&#xff0c;通过低秩转换对大型语言模型进行适应性更新&#xff0c;减少…

centos7下docker 容器实现redis主从同步

1.下载redis 镜像 docker pull bitnami/redis2. 文件夹授权 此文件夹是 你自己映射到宿主机上的挂载目录 chmod 777 /app/rd13.创建docker网络 docker network create mynet4.运行docker 镜像 安装redis的master -e 是设置环境变量值 docker run -d -p 6379:6379 \ -v /a…

SLAAC如何工作?

SLAAC如何工作&#xff1f; IPv6无状态地址自动配置(SLAAC)-常见问题 - 苍然满关中 - 博客园 https://support.huawei.com/enterprise/zh/doc/EDOC1100323788?sectionj00shttps://www.zhihu.com/question/6691553243/answer/57023796400 主机在启动或接口UP后&#xff0c;发…

2024.12.21辩论赛感受

背景 今天辩论赛的双方论点是&#xff1a; 正方&#xff1a;寒假留在研发中心的收获大 反方&#xff1a;寒假去做其他事情的收获 辩论赛&#xff0c;为了锻炼自己&#xff0c;选择了不想选择以及相对不好辩论的反方。出现的状况有一下几点&#xff1a; 1.发现自己脑子完全跟不…

【从零开始入门unity游戏开发之——C#篇21】C#面向对象的封装——`this`扩展方法、运算符重载、内部类、`partial` 定义分部类

文章目录 一、this扩展方法1、扩展方法的基本语法2、使用扩展方法3、扩展方法的注意事项5、扩展方法的限制6、总结 二、运算符重载1、C# 运算符重载2、运算符重载的基本语法3. 示例&#xff1a;重载加法运算符 ()4、使用重载的运算符5、支持重载的运算符6、不能重载的运算符7、…

C语言:文件IO

C语言&#xff1a;文件IO 文件操作 概述 什么是文件 文件是保存在外存储器&#xff08;一般代指磁盘&#xff0c;U盘&#xff0c;移动硬盘等&#xff09;的数据的集合 文件操作体现在哪几个方面 文件内容的读取文件内容的写入 数据的读取和写入可被视为针对文件进行输入&…

时间序列异常值处理方法

文章目录 一、删除法二、替换法三、插值法四、滑动窗口五、基于模型的替换 时间序列相关参考文章&#xff1a; 时间序列预测算法—ARIMA 时间序列预测算法—Prophet 时间序列分类任务—tsfresh python时间序列处理 有季节效应的非平稳序列分析 时间序列异常值检测方法 时间序列…

【报错】node:internal/modules/cjs/loader:936

报错问题&#xff1a; 当执行npm run dev后&#xff0c;出现下面错误 这个错误一般是由于Node.js无法找到所需的模块而引起的&#xff0c;解决此问题的一种方法就是重新安装所需的模块。 解决办法&#xff1a; 删除npm install 所下载在项目里的node_modules文件执行操作&…

故障诊断 | 一个小创新:特征提取+KAN分类

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 基于FFT CNN - BiGRU-Attention 时域、频域特征注意力融合的轴承故障识别模型-CSDN博客 基于FFT CNN - Transformer 时域、频域特征融合的轴承故障识别模型-CSDN博客 P…