单源最短路径算法 -- 迪杰斯科拉(Dijkstra)算法

1. 简介

        迪杰斯科拉(Dijkstra)算法是一种用于在加权图中找到最短路径的经典算法。它是由荷兰计算机科学家Edsger Wybe Dijkstra在1956年首次提出的,并以他的名字命名。这个算法特别适合于解决单源最短路径问题,即计算图中一个顶点到其他所有顶点的最短路径。

2. 核心原理

        Dijkstra算法的核心很简单,就是贪心算法的思想,它每次都选择当前已知的最短路径,并以此作为基础来更新其他顶点的最短路径估计。

注: Dijkstra算法只能用于图中所有权重为非负数,因为过程中会对路径上的权重进行累加比较。

3. 算法步骤

  1. 将源顶点的距离设为0,其他所有顶点的距离设为无穷大。
  2. 将源顶点加入已访问集合。
  3. 遍历未访问顶点,找出距离最短的顶点,将其加入已访问集合。
  4. 更新邻接顶点的距离,如果新计算的距离小于当前距离,则更新距离。
  5. 重复步骤3和4,直到所有顶点都被访问过。

4. 图解

5. 代码实现

class Graph {
    private int vertices;
    private LinkedList<Edge>[] adjacencyList;

    public Graph(int vertices) {
        this.vertices = vertices;
        adjacencyList = new LinkedList[vertices];
        for (int i = 0; i < vertices; i++) {
            adjacencyList[i] = new LinkedList<>();
        }
    }

    // 添加一个边
    public void addEdge(int source, int destination, int weight) {
        Edge edge = new Edge(source, destination, weight);
        adjacencyList[source].addFirst(edge);
    }


    public void dijkstra(int startVertex) {
        boolean[] visited = new boolean[vertices];  // 记录顶点是否被访问过
        int[] distance = new int[vertices];         // 记录起始顶点到其他顶点的最短距离

        // 初始化距离数组
        Arrays.fill(distance, Integer.MAX_VALUE);
        distance[startVertex] = 0;

        // 使用优先队列来维护待访问顶点
        PriorityQueue<Edge> pq = new PriorityQueue<>(Comparator.comparingInt(edge -> edge.weight));
        pq.offer(new Edge(-1, startVertex, 0));

        // 核心
        while (!pq.isEmpty()) {
            Edge edge = pq.poll();
            int currentVertex = edge.destination;
            
            // 如果当前顶点已经被访问过,则跳过
            if (!visited[currentVertex]) {
                visited[currentVertex] = true;

                // 更新相邻顶点的最短距离
                LinkedList<Edge> neighbors = adjacencyList[currentVertex];
                for (Edge neighbor : neighbors) {
                    // 相邻顶点未被访问过
                    if (!visited[neighbor.destination]) {
                        int newDistance = distance[currentVertex] + neighbor.weight;
                        // 如果新的距离小于当前距离,则更新距离
                        if (newDistance < distance[neighbor.destination]) {
                            distance[neighbor.destination] = newDistance;
                            pq.offer(new Edge(currentVertex, neighbor.destination, newDistance));
                        }
                    }
                }
            }
        }

        printShortestPath(distance, startVertex);
    }

    // 打印结果
    private void printShortestPath(int[] distance, int startVertex) {
        System.out.println("Shortest path from vertex " + startVertex + " to all other vertices:");
        for (int i = 0; i < vertices; i++) {
            System.out.println("To vertex " + i + ": " + distance[i]);
        }
    }

    // 边
    static class Edge {
        int source;         // 源点
        int destination;    // 目标点
        int weight;         // 权重

        public Edge(int source, int destination, int weight) {
            this.source = source;
            this.destination = destination;
            this.weight = weight;
        }
    }
}

public class DijkstraAlgorithm {
    public static void main(String[] args) {
        Graph graph = new Graph(6);
        graph.addEdge(0, 1, 4);
        graph.addEdge(0, 2, 3);
        graph.addEdge(1, 2, 1);
        graph.addEdge(1, 3, 2);
        graph.addEdge(2, 3, 4);
        graph.addEdge(2, 4, 3);
        graph.addEdge(3, 4, 2);
        graph.addEdge(3, 5, 1);
        graph.addEdge(4, 5, 6);

        graph.dijkstra(0); // Starting vertex is 0
    }
}

6. 应用场景

  1. 路由算法:在路由器中,Dijkstra算法帮助确定经过哪些中间节点可以最快地传输数据包。尽管现代互联网路由器采用的协议更为复杂,但这些协议的核心仍然是基于Dijkstra算法的。
  2. 交通规划:在城市交通网络中,通过Dijkstra算法计算最短路径,可以设计更有效的交通网络,减少拥堵并提高效率。尽管实际的规划功能可能会使用更复杂的算法来考虑交通状况、路况等因素,Dijkstra算法的基本思想仍然被广泛应用。
  3. 社交网络:在社交网络分析中,Dijkstra算法可以帮助识别人与人之间的最短联系链。例如,在一个社交网络中,想要找到连接两个特定用户的最短关系链时,Dijkstra算法能够派上用场。这在实现某些社交功能,如“你可能认识的人”推荐时非常有用。
  4. 通信网络设计:设计电话网络或有线电视网络时,Dijkstra算法可以帮助确定最佳的电缆或光纤布线路径,以最小化成本同时保证服务质量。这是通过计算中心节点(如交换机或分配器)到所有其他节点的最短路径来实现的。

7. 优缺点

优点:

  • 简单易懂,实现简单。
  • 适用于有向图和无向图。
  • 时间复杂度较低,在稀疏图中表现较好。

缺点:

  • 不能处理负权边。
  • 空间复杂度较高,毕竟需要存储所有顶点的最短距离。
  • 不适用于大规模图,效率较低。

8. 总结

           总而言之,Dijkstra算法是一种用于解决单源最短路径问题的算法,适用于带权有向图或无向图。算法的主要思想是贪心策略,即每次都寻找距离源点最近的一个顶点,然后更新其相邻顶点的距离。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在自己的电脑上搭建我的世界Java版服务器

很多朋友&#xff0c;喜欢玩Minecraft&#xff0c;也希望搭建一个服务器&#xff0c;用于和小伙伴联机&#xff1b; 并且&#xff0c;拥有服务器后&#xff0c;即使所有玩家都下线&#xff0c;“世界”依旧在运行&#xff0c;玩家可以随时参与其中&#xff0c;说不定一上线&am…

栈和队列(适配器模式模拟)

文章目录 声明stack的介绍queue的介绍deque双端队列简单介绍&#xff08;了解&#xff09;概述优缺点 适配器模式通过容器适配器模拟stack通过容器适配器模拟queue 总结 声明 模拟实现源代码已上传至gitee仓库&#xff1a;stack_queue_learn stack的介绍 stack文档介绍 sta…

go语言 | 快速生成数据库表的 model 和 queryset

就是生成 model 目录的 xxx.go 和 xxx_gen.go 文件 使用的工具&#xff1a; 快速生成 model&#xff1a;gentool&#xff1a;https://github.com/go-gorm/gen/tree/master/tools/gentool 根据 model 生成 queryset&#xff1a;go-queryset&#xff1a;https://github.com/jirfa…

开源大模型之辩:真假开源

目录 前言开源的定义什么是开源大模型&#xff1f;大模型时代首次出现闭源和开源“齐头并进”开源和闭源不是绝对对立的 大模型到底开源什么&#xff1f;传统开源软件与开源大模型的差别开源软件让开源大模型“受益匪浅” 不同大模型企业&#xff0c;开源、闭源策略不同开源…

SQL 窗口函数

1.窗口函数之排序函数 RANK, DENSE_RANK, ROW_NUMBER RANK函数 计算排序时,如果存在相同位次的记录,则会跳过之后的位次 有 3 条记录排在第 1 位时: 1 位、1 位、1 位、4 位…DENSE_RANK函数 同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次 有 3 条记录排在…

SPI 配置寄存器程序

/************************************************** * **************************************************/ module zhm_mspi #( parameter C_SPI_CPHA 1 ,// clock phase &#xff0c;0&#xff0c;在 SCLK 的第一个跳变沿进行采样&#xff1b;1&…

Linux和Windows下查看CPU运行频率的方法

文章目录 0.前言1.Linux系统中查看CPU运行频率的方法&#xff08;经测试在UnRaid中适用的&#xff09;1.1.最简单的lscpu命令1.2.查看CPU实时运行频率的watch -n 1 cpufreq-info命令 2.WIndows系统中查看CPU运行频率的方法2.1.系统属性大法2.2.任务管理器大法2.3.CPU-Z等硬件检…

Codeforces Global Round 26 D. “a“ String Problem 【Z函数】

D. “a” String Problem 题意 给定一个字符串 s s s&#xff0c;要求把 s s s 拆分成若干段&#xff0c;满足以下要求&#xff1a; 拆分出来的每一个子段&#xff0c;要么是子串 t t t&#xff0c;要么是字符 a a a子串 t t t 至少出现一次 t ≠ " a " t \ne…

零基础非科班也能掌握的C语言知识22 预处理详解(完结)

预处理详解 1.预处理符号2.#define 定义常量3.#define 定义宏4.带有副作用的宏参数5.宏替换的规则6.宏函数的对比6.1 例子6.1 .16.1.26.1.3 7.命名约定8.undefin9.命令行定义(博主没办法演示)10.条件编译11.头文件的包含11.1本地文件11.2库文件的包含11.3 嵌套文件的包含 12.其…

python实现自动化测试框架如何进行数据参数化?这个包可以了解下

1.数据参数化介绍 只要你是负责编写自动化测试脚本的&#xff0c;数据参数化这个思想你就肯定会用 &#xff0c;数据参数化的工具你肯定的懂一些 &#xff0c;因为它能大大的提高我们自动化脚本编写效率 。 1.1什么是数据参数化 所谓的数据参数化 &#xff0c;是指所执行的测…

Unity 自定义房间布局系统 设计与实现一个灵活的房间放置系统 ——物体占用的区域及放置点自动化

放置物体功能 效果&#xff1a; 功能&#xff1a; 自定义物体占用区域的大小一键调整占用区域调整旋转度数&#xff0c;分四个挡位&#xff1a; NoRotation&#xff1a;该物体不能调整旋转。MaximumAngle&#xff1a;每次转动90。NormalAngle&#xff1a;每次转动45&#xff…

Solr 日志系统7.4.0部署和迁移到本地,Core Admin 添加新的core报错

文章目录 Solr部署Docker部署二进制部署 Tips:Solr设置账号密码方法1&#xff1a;(不使用)方法2&#xff1a; Core Admin 添加新的core报错Solr数据迁移 Solr部署 Docker部署 docker run -d -p 8983:8983 --name solr solr:latest docker run -d -p 8983:8983 -v /opt/solr:/…

操作系统入门系列-MIT6.828(操作系统工程)学习笔记(五)---- 操作系统的组织结构(OS design)

系列文章目录 操作系统入门系列-MIT6.S081&#xff08;操作系统&#xff09;学习笔记&#xff08;一&#xff09;---- 操作系统介绍与接口示例 操作系统入门系列-MIT6.828&#xff08;操作系统工程&#xff09;学习笔记&#xff08;二&#xff09;----课程实验环境搭建&#x…

网工内推 | 深信服、中软国际技术支持工程师,最高13k*13薪

01 深信服 &#x1f537;招聘岗位&#xff1a;远程技术支持工程师 &#x1f537;任职要求&#xff1a; 一、专业能力和行业经验&#xff1a; ①具备友商同岗位工作经验1.5年以上&#xff0c;具备良好的分析和判断能力&#xff0c;有独立问题处理思路&#xff0c;具备常见协…

python中魔术方法__str__与__repr__的区别

在Python中&#xff0c;__str__和__repr__是两个常见的魔法方法&#xff08;也称为双下方法或dunder方法&#xff09;&#xff0c;它们用于定义对象的字符串表示形式。它们的主要区别在于它们的用途和使用场景。 __str__ 用途&#xff1a;__str__方法用于为用户提供一个易读的…

【嵌入式DIY实例】-Nokia 5110显示DHT11/DHT22传感器数据

Nokia 5110显示DHT11/DHT22传感器数据 文章目录 Nokia 5110显示DHT11/DHT22传感器数据1、硬件准备2、代码实现2.1 显示DHT11数据2.2 显示DHT22数据本文介绍如何将 ESP8266 NodeMCU 开发板 (ESP-12E) 与 DHT11 数字湿度和温度传感器以及诺基亚 5110 LCD 连接。 NodeMCU 从 DHT11…

.NET Core 服务注册步骤总结

总结一下 .NET Core 服务注册的步骤&#xff1a; .NET Core Web Api 项目服务注册步骤&#xff1a; 创建一个接口&#xff0c;和实现类 比如&#xff1a;IMyService, CnService 在 Program.cs 的 var app builder.Build(); 语句之前加上&#xff1a; var builder WebApplic…

【面经总结】 Java基础 - 异常

异常 介绍一下 Java 的异常体系 Java 的异常体系是由 Throwable 类及其子类构成的。 Throwable 包含两个子类&#xff1a;Error&#xff08;错误&#xff09;和 Exception&#xff08;异常&#xff09; Error 表示错误&#xff0c;通常不需要程序员处理&#xff0c;如内存溢…

python中的turtle

turtle个别指令 初始箭头默认指向为东&#xff08;右&#xff09; 往前&#xff08;右&#xff09;三个格&#xff1a;turtle.forward(3) 往后&#xff08;左&#xff09;三个格&#xff1a;turtle.backward(3) 往左转90度&#xff1a;turtle.left(90) 往右转90度&#xf…

Attention与轻量级ResNet融合,低资源消耗下实现效率和性能完美平衡

注意力机制通过让模型关注图像关键区域提升了识别精度&#xff0c;而轻量级残差网络通过减少参数和计算量&#xff0c;实现了在低资源消耗下的优秀性能。 结合注意力机制与轻量级残差网络&#xff0c;既能让模型能够更高效地关注输入数据中的关键信息&#xff0c;提升模型处理…