Dijkstra单源最短路径算法学习有感

news2024/9/22 4:04:29

认识Dijkstra

艾兹格·维布·迪克斯特拉(Edsger Wybe Dijkstra,/ˈdaɪkstrə/ DYKE-strə;荷兰语:[ˈɛtsxər ˈʋibə ˈdɛikstra] 1930年5月11日-2002年8月6日)是一位荷兰计算机科学家、程序员、软件工程师、系统科学家和科学散文家。他因对开发结构化编程语言做出的基础贡献而获得了1972年的图灵奖,并担任德克萨斯大学奥斯汀分校的斯伦贝谢百年计算机科学主席,任职时间从1984年到2000年。在他于2002年去世前不久,他因其在程序计算的自稳定性方面的工作而获得了ACM PODC分布式计算有影响力论文奖。为了纪念他,该年度奖项在接下来的一年更名为迪克斯特拉奖。

迪克斯特拉在计算机科学领域的贡献

  1. 最短路径算法,也称为迪克斯特拉算法,现代计算机科学本科课程中广泛教授
  2. Shunting yard算法
  3. THE OS 操作系统
  4. 银行家算法
  5. 用于协调多个处理器和程序的信号量构造
  6. 在分布式计算领域提出概念:自稳定性

认识Dijkstra 算法

Dijkstra算法是一种用于解决单源最短路径问题的经典算法,由荷兰计算机科学家Edsger W. Dijkstra于1956年提出。该算法能够找出从一个节点到其他所有节点的最短路径。

需要注意的是,Dijkstra算法要求图中的边权重必须为非负数,否则无法保证得到正确的最短路径。如果图中存在负权边,可以使用其他算法如Bellman-Ford算法来解决最短路径问题。

Dijkstra算法描述

  1. 将所有顶点标记为未访问。创建一个未访问顶点的集合。
  2. 为每个顶点分配一个临时距离值
    • 对于我们的初始顶点,将其设置为零
    • 对于所有其他顶点,将其设置为无穷大。
  1. 每次选择最小临时距离的未访问顶点,作为新的当前顶点
  2. 对于当前顶点,遍历其所有未访问的邻居,并更新它们的临时距离为更小
    • 例如,1->6 的距离是 14,而1->3->6 的距离是11。这时将距离更新为 11
    • 否则,将保留上次距离值
  1. 当前顶点的邻居处理完成后,把它从未访问集合中删除
/**
     * 迪杰斯特拉算法 - 计算图的最短路径
     *
     * @param graph 图
     * @param v     初始顶点
     */
private static void dijkstra(List<Vertex> graph, Vertex v) {
    // 1.将所有顶点标记为未访问,创建一个未访问顶点的集合
    List<Vertex> list = new ArrayList<>(graph);
    // 2.为每个顶点分配一个临时距离值
    // 2.1:对于初始顶点,临时距离值为0;
    v.dict = 0;
    while (!list.isEmpty()) {
        // 3.选择最小临时距离的未访问顶点作为新的当前顶点【选取当前节点】
        Vertex curr = chooseMinDictVertex(list);
        // 4.对于当前顶点,遍历所有未访问的邻居,并更新它们的临时距离为更小
        updateNeighboursDict(curr);
        // 5.当前顶点的邻居处理完成后,把它从未访问集合中删除
        list.remove(curr);
        // 表示当前节点已被访问
        curr.visited = true;
    }
    for (Vertex vertex : graph) {
        System.out.println(vertex.getName() + "::" + vertex.dict + "::" + (vertex.prev != null ? vertex.prev.name : "null"));
    }
}

/**
     * 选择最小临时距离的未访问顶点作为新的当前顶点【可优化,使用优先级队列,参考下面的代码】
     * @param list 未访问顶点集合
     * @return 临时距离最小的顶点
     */
private static Vertex chooseMinDictVertex(List<Vertex> list) {
    // 默认未访问顶点集合中第一个顶点的距离最小
    Vertex min = list.get(0);
    // 遍历未访问顶点集合,如果发现有距离更小的顶点,则更新距离最小的顶点引用
    for (int i = 1; i < list.size(); i++) {
        if (list.get(i).dict < min.dict) {
            min = list.get(i);
        }
    }
    return min;
}

/**
     * 对于当前顶点,遍历所有未访问的邻居,并更新它们的临时距离为更小
     * @param curr 当前顶点
    */
private static void updateNeighboursDict(Vertex curr) {
    for (Edge edge : curr.edges) {
        // 获取邻居顶点
        Vertex neighbour = edge.linked;
        // 如果邻居顶点未访问(任然存在于未访问集合中)
        if (!neighbour.visited) {
            // 计算从当前顶点到邻居的距离
            int dict = curr.dict + edge.weight;
            // 如果这个距离小于之前邻居顶点中维护的距离值,则更新这个距离
            if (dict < neighbour.dict) {
                neighbour.dict = dict;
                // 记录当前节点的路径从何而来
                neighbour.prev = curr;
            }
        }
    }
}

改进 - 优先级队列

  1. 创建一个优先级队列,放入所有顶点(队列大小会达到边的数量)
  2. 为每个顶点分配一个临时距离值
    • 对于我们的初始顶点,将其设置为零
    • 对于所有其他顶点,将其设置为无穷大。
  1. 每次选择最小临时距离的未访问顶点,作为新的当前顶点
  2. 对于当前顶点,遍历其所有未访问的邻居,并更新它们的临时距离为更小,若距离更新需加入队列
    • 例如,1->6 的距离是 14,而1->3->6 的距离是11。这时将距离更新为 11
    • 否则,将保留上次距离值
  1. 当前顶点的邻居处理完成后,把它从队列中删除

使用优先级队列优化上面步骤三的部分

/**
     * 迪杰斯特拉算法 - 计算图的最短路径
     *
     * @param graph 图
     * @param v     初始顶点
     */
private static void dijkstra(List<Vertex> graph, Vertex v) {
    // 1.创建一个优先级队列(默认小顶堆),放入所有顶点(队列大小会达到边的数量)
    PriorityQueue<Vertex> queue = new PriorityQueue<>(Comparator.comparing(vertex -> vertex.dict));
    for (Vertex vertex : graph) {
        queue.offer(vertex);
    }
    // 2.为每个顶点分配一个临时距离值
    // 2.1:对于初始顶点,临时距离值为0;
    v.dict = 0;
    while (!queue.isEmpty()) {
        // 3.选择最小临时距离的未访问顶点作为新的当前顶点
        Vertex curr = queue.peek();
        // 4.对于当前顶点,遍历其所有未访问的邻居,并更新它们的临时距离为更小,若距离更新需加入队列
        if (!curr.visited) {
            updateNeighboursDict(curr, queue);
            // 表示当前节点已被访问
            curr.visited = true;
        }
        // 5.当前顶点的邻居处理完成后,把它从未访问集合中删除
        queue.poll();
    }
    graph.forEach(vertex -> System.out.println(vertex.name + "::" + vertex.dict + "::" + (vertex.prev != null ? vertex.prev.name : "null")));
}

/**
     * 对于当前顶点,遍历其所有未访问的邻居,并更新它们的临时距离为更小,若距离更新需加入队列
     *
     * @param curr  当前顶点
     * @param queue 优先级【按照顶点距离】队列
     */
private static void updateNeighboursDict(Vertex curr, PriorityQueue<Vertex> queue) {
    for (Edge edge : curr.edges) {
        // 获取邻居顶点
        Vertex neighbour = edge.linked;
        // 如果邻居顶点未访问(任然存在于未访问集合中)
        if (!neighbour.visited) {
            // 计算从当前顶点到邻居的距离
            int dict = curr.dict + edge.weight;
            // 如果这个距离小于之前邻居顶点中维护的距离值,则更新这个距离
            if (dict < neighbour.dict) {
                neighbour.dict = dict;
                neighbour.prev = curr;
                // 更新距离需要加入队列
                queue.offer(neighbour);
            }
        }
    }
}

Dijkstra 算法存在的问题

按照 Dijkstra 算法,得出

  • v1 -> v2 最短距离2
  • v1 -> v3 最短距离1
  • v1 -> v4 最短距离2

事实应当是

  • v1 -> v2 最短距离2
  • v1 -> v3 最短距离0
  • v1 -> v4 最短距离1

Dijkstra 算法无法处理带有负权边的图的最短路径问题

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

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

相关文章

(回溯) LeetCode 46. 全排列

原题链接 一. 题目描述 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a;…

零基础学习Redis(1) -- Redis简介

Redis是一个在内存中存储数据的一个中间组件&#xff0c;可用作数据库或数据缓存&#xff0c;通常在分布式系统中使用 &#xff08;不了解分布式&#xff1f; 点击传送&#xff09; 1. Redis特性 在内存中存储数据&#xff0c;通过键值对的方法存储key为string&#xff0c;v…

[GYCTF2020]FlaskApp1

打开题目 简单的一个base64加解密小程序 查看提示&#xff0c;好像并没有什么用&#xff0c;题目是flask&#xff0c;可能是ssti模板注入 加密窗口{{77}},解密窗口e3s3Kzd9fQ ({{77}} 加密窗口没看到注入&#xff0c;解密窗口存在注入&#xff0c;是模板注入 读取文件内容&am…

JimV私有云平台部署及应用

1. JimV概述 1.1 介绍 JimV 是一个&#xff0c;结构精简&#xff0c;易于部署、维护、使用的&#xff0c;企业私有云管理平台。JimV 基于 KVM 开发而来&#xff0c;通过 JimV 管理平台&#xff0c;可以批量创建、管理虚拟机。 JimV 更为轻量级&#xff0c;使用户轻易拥有维护…

【Day05】0基础微信小程序入门-学习笔记

文章目录 基础加强学习目标使用npm包1.准备项目2. 小程序对于npm的支持和限制3. Vant Weapp小程序UI组件库4. 使用Vant组件5. 定制全局主题样式6. API Promise化 全局数据共享1. 简介2. MobX2.1 安装MobX相关包并构建npm2.2 创建MobX的Store实例2.3 将Store成员绑定到页面中2.4…

SpringBoot统一功能

目录 前言1&#xff1a;首先要明白&#xff0c;什么是统一功能&#xff1f; 前言2&#xff1a;统一功能包括哪些呢&#xff1f;展开说说&#xff1f; 一、拦截器&#xff08;interceptor&#xff09; 1、介绍 2、如何使用拦截器 3、拦截器的在程序内部的执行流程是啥呢&a…

MySQL关键字—using和on

文章目录 1. MySQL关键字—using和on1.1 using关键字的概念 2. using和on的区别2.1 USING 子句2.2 ON 子句 3. 示例对比3.1 建表&#xff1a;3.2 准备数据3.3 结果 1. MySQL关键字—using和on 1.1 using关键字的概念 连接查询时如果是同名字段作为连接条件&#xff0c;using可…

ctfhub Bypass disable_function(完结)0

LD_PRELOAD url 蚁剑连接 选择插件 点击开始 查看到此文件名编辑连接拼接到url后面重新连接 点击开启终端 在终端执行命令 ls / /readfile ShellShock url CTFHub 环境实例 | 提示信息 蚁剑连接 写入shell.php <?phpeval($_REQUEST[ant]);putenv("PHP_test() { :…

四款AI写作免费工具,让文案工作更轻松

作为一名文案编辑&#xff0c;我算是跟文字打了几年的交道了。最近&#xff0c;AI写作这股风潮真是吹得热火朝天&#xff0c;我也忍不住尝了尝鲜&#xff0c;试了试几款神器。说实话&#xff0c;这体验还挺有意思的&#xff0c;感觉就像是在文字的世界里开了一场高科技的派对。…

Redis:概念、部署、配置、优化

目录 关系型数据库与非关系型数据库 关系型数据库 非关系型数据库 非关系型数据库存在的原因 Redis 概念 优点 Redis部署流程 初步设置 安装 初始化 初始化时指定的参数说明 Redis配置文件 修改监听地址 Redis远程连接 远程连接 测试服务端状态 redis-benchm…

智慧景区系统:科技赋能旅游新体验

随着信息技术的飞速发展&#xff0c;旅游业正经历着前所未有的变革&#xff0c;智慧景区系统作为这一变革的先锋&#xff0c;正以其独特的魅力重塑着游客的旅行方式。智慧景区系统&#xff0c;顾名思义&#xff0c;是运用物联网、大数据、云计算、人工智能等现代信息技术&#…

Git客户端 TortoiseGit下载

1.概述 使用TortoiseGit比直接使用git客户端和命令来实现代码管理更为方便&#xff0c;本文贴出了软件的下载地址和基本配置信息 2.TortoiseGit安装与配置 TortoiseGit是TortoiseSVN的Git版本&#xff0c;是一个在Windows系统下使用的Git版本控制客户端。它提供了图形用户界…

MIT线性代数P5

置换矩阵 置换矩阵是行重新排列的单位矩阵。 置换矩阵用P表示&#xff0c; 性质&#xff1a; n阶置换矩阵共有n!个

37.x86游戏实战-XXX遍历怪物数组

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

0812|TCP和UDP跨主机通信

思维导图 TCP实现跨主机通信 服务器端 #include<myhead.h> #define SER_PORT 6666 //端口号 #define SER_IP "192.168.0.108" //服务器IP int main(int argc, const char *argv[]) {//创建套接字文件int sfd socket(AF_INET,SOCK_STREAM,0);if(sfd -1){pe…

进阶!haproxy高级功能与配置

文章目录 前言基于cookie的会话保持IP透传四层IP透传未开启状态开启透传状态 七层IP透传 自定义错误界面重定向HAProxy 四层负载之数据库HAProxy https 前言 本文主要介绍HAProxy高级配置及使用案例 文章相关连接如下&#xff1a; 如果想深入了解haproxy算法的相关知识&…

基于Python+Django+Vue+Mysql前后端分离的图书管理系统

利用空闲休息时间开始自己写了一套图书管理系统。现将源码开源&#xff0c;项目遇到问题 PythonDjangoVue图书管理系统开发全流程 大家好&#xff0c;我是程序员科科&#xff0c;这是我开源的基于PythonDjangoVue的图书管理系统 希望可以帮助想学前后端分离的同学 项目中遇…

积极创新模式,推动智慧场馆建设

智慧场馆是指基于信息技术应用的场馆建设模式&#xff0c;利用物联网、云计算、大数据分析等技术手段&#xff0c;实现场馆资源的管理优化、运营效率的提升以及用户体验的改善。智慧场馆在我国得到了广泛的政策支持和推动&#xff0c;政府出台了一系列鼓励智慧场馆建设的政策措…

Java SIP Client

采用JAIN SIP API实现一个SIP客户端实现向SIP服务器注册。SIP服务器可以为FreeSWITCH也可以为满足GB28181的SIP平台。话不多说直接看注册流程图&#xff1a; 代码实现&#xff1a; 创建maven工程添加依赖 <dependencies><dependency><groupId>javax.sip</…

Apple Maps现在可在Firefox和Mac版Edge浏览器中使用

Apple Maps最初只能在 Windows 版 Safari、Chrome 浏览器和 Edge 浏览器上运行&#xff0c;现在已在其他浏览器上运行&#xff0c;包括 Mac 版 Firefox 和 Edge。经过十多年的等待&#xff0c;Apple Maps于今年 7 月推出了新版地图应用的测试版&#xff0c;但只能在有限的浏览器…