图论算法 --Dijkstra

news2025/1/24 17:49:29

当谈到计算机科学时,算法是一个重要的话题,因为它们能帮助解决很多问题。而有些算法,其高效性和惊人表现,令人感到惊艳。一起来分享一下你认为令人惊艳的高效算法吧!

Dijkstra算法

    • 一、你在工作和学习中用到过哪些惊艳的算法?(包括但不限于数据科学、计算机视觉、自然语言处理等多个领域的算法)
    • 二、请你介绍一下上述算法并进行一下简单演示吧!
      • 1. Dijkstra 是什么?
      • 2. Dijkstra 算法过程
      • 3. 算法实现:
    • 三、如何优化算法才能获得更好的结果呢?你平时是从哪些思路进行优化的?
      • 1. 算法的优缺点:
      • 2. 算法优化:
    • 四、在使用算法的过程中需要注意哪些细节才能使其发挥最大的效能呢?

一、你在工作和学习中用到过哪些惊艳的算法?(包括但不限于数据科学、计算机视觉、自然语言处理等多个领域的算法)

Dijkstra算法: 一种用于寻找图中单源最短路径的贪心算法。

二、请你介绍一下上述算法并进行一下简单演示吧!

1. Dijkstra 是什么?

  Dijkstra算法是一种用于寻找图中单源最短路径的贪心算法。它通过不断扩展距离当前源点最近的节点来确定下一个待处理的节点,直到找到目标节点为止。
譬如下图 假如路径和长度已知,那么可以使用dijkstra算法计算西宁到图中所有节点的最短距离。
请添加图片描述

2. Dijkstra 算法过程

  Dijkstra算法的过程如下:

初始化:假设有n个顶点,每个顶点都有一个表示到源点的距离的数组dist。将所有顶点的dist初始化为无穷大,源点的距离设为0。

选择当前距离源点最近的未确定节点u。

更新与u相邻的所有节点的dist值,如果发现更短的路径,则更新它们的dist值。

重复步骤2和3,直到找到目标节点或所有的节点都被处理过。

返回dist数组作为结果,其中dist[i]表示从源点到顶点i的最短距离。


图解


在这里插入图片描述
  • 重复二的操作,直到所有点都确定。
    在这里插入图片描述

  • Dijkstra算法的时间复杂度为O(n^2), 用图来说明就是:

      假设有如下无向图,其中每条边的边权均为正整数。

    A-B-C-D-E
    |         |
    F         G
    
    

      我们要计算从顶点A到顶点E的最短路径长度。可以使用Dijkstra算法来实现。
    首先,将所有顶点的dist值初始化为无穷大,源点的距离设为0。然后选择当前距离源点最近的未确定节点u。在这个例子中,选择顶点A作为当前处理的节点。

         u       v       dist    A->E
    A       B       1      0   / \     / \
    A       C       2      1   |   |     |
    A       D       3      2   |   |     |
    A       E       4      3   |   |     |
    B       C       2      1  / \    / \     |
    B       D       3      2  / \    / \     |
    B       E       4      3  / \    / \     |
    C       D       3      2     |   |     |
    C       E       4      3     |   |     |
    D       E       4      3     |   |     |
    
    

      接下来,我们需要更新与u相邻的所有节点的dist值,如果发现更短的路径,则更新它们的dist值。在这个例子中,我们需要更新顶点B、C和D的dist值。具体来说,我们需要将顶点B、C和D分别与顶点A相连的边权进行比较,如果发现更短的路径,则更新它们的dist值。最终得到的结果如下所示:

         u       v       dist    A->E
    A       B       1      0   / \     / \
    A       C       2      1   |   |     |
    A       D       3      2   |   |     |
    A       E       4      3   |   |     |
    B       C       2      1  / \    / \     |
    B       D       3      2  / \    / \     | // 将B的dist更新为1,因为它与A相连的边的边权更小
    B       E       4      3  / \    / \     | // 将B的dist更新为1,因为它与A相连的边的边权更小
    C       D       3      2     |   |     | // 将C的dist更新为2,因为它与A相连的边的边权更小
    C       E       4      3     |   |     | // 将C的dist更新为2,因为它与A相连的边的边权更小
    D       E       4      3     |   |     | // 将D的dist更新为3,因为它与A相连的边的边权更小
    
    

      最后,我们得到了一个长度为4的dist数组,表示从源点A到顶点E的最短路径长度。


    3. 算法实现:

    package 图论;
    
    import java.util.ArrayDeque;
    import java.util.Comparator;
    import java.util.PriorityQueue;
    import java.util.Queue;
    import java.util.Scanner;
    
    public class dijkstra {
    	static class node
    	{
    		int x; //节点编号
    		int lenth;//长度
    		public node(int x,int lenth) {
    			this.x=x;
    			this.lenth=lenth;
    		}
    	}
    
    	public static void main(String[] args) {
    		 
    		int[][] map = new int[6][6];//记录权值,顺便记录链接情况,可以考虑附加邻接表
    		initmap(map);//初始化
    		boolean bool[]=new boolean[6];//判断是否已经确定
    		int len[]=new int[6];//长度
    		for(int i=0;i<6;i++)
    		{
    			len[i]=Integer.MAX_VALUE;
    		}
    		Queue<node>q1=new PriorityQueue<node>(com);
    		len[0]=0;//从0这个点开始
    		q1.add(new node(0, 0));
    		int count=0;//计算执行了几次dijkstra
    		while (!q1.isEmpty()) {
    			node t1=q1.poll();
    			int index=t1.x;//节点编号
    			int length=t1.lenth;//节点当前点距离
    			bool[index]=true;//抛出的点确定
    			count++;//其实执行了6次就可以确定就不需要继续执行了  这句可有可无,有了减少计算次数
    			for(int i=0;i<map[index].length;i++)
    			{
    				if(map[index][i]>0&&!bool[i])
    				{
    					node node=new node(i, length+map[index][i]);
    					if(len[i]>node.lenth)//需要更新节点的时候更新节点并加入队列
    					{
    						len[i]=node.lenth;
    						q1.add(node);
    					}
    				}
    			}
    		}		
    		for(int i=0;i<6;i++)
    		{
    			System.out.println(len[i]);
    		}
    	}
    	static Comparator<node>com=new Comparator<node>() {
    
    		public int compare(node o1, node o2) {
    			return o1.lenth-o2.lenth;
    		}
    	};
    
    	private static void initmap(int[][] map) {
    		map[0][1]=2;map[0][2]=3;map[0][3]=6;
    		map[1][0]=2;map[1][4]=4;map[1][5]=6;
    		map[2][0]=3;map[2][3]=2;
    		map[3][0]=6;map[3][2]=2;map[3][4]=1;map[3][5]=3;
    		map[4][1]=4;map[4][3]=1;
    		map[5][1]=6;map[5][3]=3;	
    	}
    }
    
    
    

    请添加图片描述


    三、如何优化算法才能获得更好的结果呢?你平时是从哪些思路进行优化的?

    1. 算法的优缺点:

      Dijkstra算法适用于以下场景:

    • 寻找两点之间的最短路径。
    • 需要在边权为负数或浮点数的图中计算最短路径。
    • 图中顶点的个数比较小,可以承受O(n^2)的时间复杂度。
    • 不需要考虑负权重的边。
    • 源点和目标点固定,只需要计算它们之间的最短路径。

      Dijkstra算法不适用于以下场景:

    • 图中顶点的个数很大,计算时间会很长。
    • 边权可能为负数或浮点数,需要使用其他算法来处理。
    • 需要考虑负权重的边,可以使用Bellman-Ford算法或Edmonds-Karp算法。
    • 需要同时寻找多个起点到某个定点的最短路径,可以使用Dinic算法。

    2. 算法优化:

    1. 使用最小堆来加速选择当前距离源点最近的未确定节点的过程,可以将堆调整为最大堆以保证最小堆性质。
    2. 对于有负边权或浮点数边权的图,可以使用其他算法来处理,例如Bellman-Ford算法或Edmonds-Karp算法。
    3. 对于稠密图或具有限制的顶点数的图,可以使用Dijkstra算法的变体,例如SPFA算法或A*算法。
    4. 使用并行化技术来加速Dijkstra算法的执行,例如使用多线程或分布式计算技术。
    5. 在实际应用中,可以根据具体情况选择合适的优化方法,例如结合多种算法进行混合优化等。

    四、在使用算法的过程中需要注意哪些细节才能使其发挥最大的效能呢?

    细节注意
      以下是使用Dijkstra算法时需要注意的一些细节,以使其发挥最大的效能:

    1. 确定源点和目标点:在使用Dijkstra算法之前,必须先确定源点和目标点。源点表示要计算最短路径的起点,目标点表示要计算最短路径的终点。

    2. 选择合适的数据结构:Dijkstra算法需要使用一个最小堆来存储未确定节点的信息。因此,在实际应用中,需要选择合适的数据结构来存储顶点的信息。常用的数据结构包括数组、链表、二叉堆等。

    3. 初始化dist数组:在使用Dijkstra算法之前,需要对dist数组进行初始化。对于无向图或有向图中的每个顶点i,将dist[i]初始化为无穷大(表示该顶点到源点的距离为无限大)。

    4. 更新dist数组:在更新dist数组时,需要比较与当前节点相邻的所有节点的dist值,并更新距离源点最近的未确定节点的dist值。更新dist值时,需要使用min-heap来保证正确的顺序。

    5. 处理负边权或浮点数边权的情况:如果存在负边权或浮点数边权的情况,需要使用其他算法来处理。例如,可以使用Bellman-Ford算法或Edmonds-Karp算法来处理带负边权或浮点数边权的图。

    6. 避免重复遍历:在更新dist数组的过程中,需要避免重复遍历相同的顶点。为了避免这种情况的发生,可以使用一个哈希表来记录已经遍历过的顶点。

    7. 考虑边界情况:在使用Dijkstra算法时,需要考虑边界情况。例如,当所有顶点的dist值都为无穷大时,表示不存在从源点到目标点的路径;当所有顶点的dist值都相等时,表示存在多条从源点到目标点的路径。



    部分参考:
    Dijkstra算法详细(单源最短路径算法)

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

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

相关文章

半导体器件基础(期末模电速成)

目录 1、半导体分类 2、PN结 3、二极管 4、稳压二极管 5、三极管 6、场效应管 1、半导体分类 2、PN结 3、二极管 伏安特性&#xff1a; 我们第七版模电书上给的正向导通压降分别约为0.7和0.2V&#xff0c;且硅的单向导电性更好 如何确定二极管状态&#xff1f; 阳极电压…

C++ 输出格式控制

C 输出格式控制 需包含头文件&#xff1a; 浮点数精度、域宽、填充 操作符功能right-alignedright-alignedsetprecision(int n)设置以n表示的数值精度setw(int n)设置以n表示的域宽setfill(char c)设置以c表示的填充字符 输出格式 操作符功能oct以八进制格式输出数据dec以…

事件循环机制

基本概念 聊一下事件循环机制&#xff0c;在开始这篇文章之前&#xff0c;先明确一个概念&#xff0c;js本身是没有事件循环这个定义的。是js被嵌入相应的执行环境&#xff08;浏览器 / Nodejs&#xff09;&#xff0c;配合当前事件循环的组成部分&#xff0c;具体来说分下面两…

【基于容器的部署、扩展和管理】3.4 灰度发布和A/B测试

往期回顾&#xff1a; 第一章&#xff1a;【云原生概念和技术】 第二章&#xff1a;【容器化应用程序设计和开发】 第三章&#xff1a;【3.1 容器编排系统和Kubernetes集群的构建】 第三章&#xff1a;【3.2 基于容器的应用程序部署和升级】 第三章&#xff1a;【3.3 自动…

【C++】引用和右值引用

目录 1. 引用 1.1 引用的概念 1.2 引用的特性 1.3 引用的使用场景 1.3.1 作为参数 1.3.2 作为返回值 1.4 常量引用 1.5 引用和指针的区别 2. 左值和右值 3. 右值引用 3.1 右值引用的概念 3.2 左值持久&#xff1b;右值短暂 3.3 变量是左值 3.4 标准库move函数 1.…

docker使用与服务器上的可视化(ROS rviz等)

1.安装docker 安装docker&#xff1a;官网教程&#xff0c;按照官网命令一步步来即可。 添加当前用户到docker用户组&#xff1a; 【docker】添加用户到docker组&#xff0c;这样后面运行docker的时候前面不需要加sudo命令&#xff0c;否则运行docker的时候一直需要在前面加su…

开发人员必备的万能工具箱:He3

目录 1.简介2.安装3.详细功能清单4.常用快捷键5.使用示例5.1 测试正则表达式5.2 文本比较 He3官网&#xff1a; https://he3.app/zh/ 1.简介 今天&#xff0c;给大家推荐一款开发人员必备的万能工具箱&#xff1a;He3&#xff0c;这是一款免费的开发者工具箱&#xff0c;截至…

十分钟,零基础使用uniCloud完成后端管理系统搭建一

本文主要是通过uniCloud搭建后端管理系统&#xff0c;适合小白开发者、个人开发者&#xff0c;零后端基础&#xff0c;快速、低成本完成后端管理系统搭建。 还未创建uniCloud服务空间的开发者可以查看我的文章&#xff1a;Dcloud开发者注册&#xff0c;uniCloud服务空间创建。…

电脑显示屏不亮但是主机已开机?5种原因以及解决方案

电脑与我们的日常生活和工作密切相关&#xff0c;缺了它我们工作就很难正常展开。电脑使用久了&#xff0c;难免出现一些小问题&#xff0c;比如&#xff1a;电脑显示屏不亮但是主机已开机&#xff0c;这是什么原因造成的&#xff1f;我们应该怎么处理&#xff1f; 可能很多人…

随机数发生器设计(四)

随机数发生器设计&#xff08;四&#xff09;- DRNG 概述1 内部状态2 初始化函数3 SM3派生函数4 其他部分 概述 本示例DRNG设计参考了GM/T 0105 &#xff0c;基于SM3算法实现&#xff0c;内部功能接口包括初始化函数、重播种函数、输出函数和已知答案自测试函数&#xff0c;同…

正点原子STM32(基于HAL库)5

目录 SRAM 实验存储器简介SRAM 方案简介硬件设计程序设计程序流程图程序解析 下载验证 内存管理实验内存管理简介硬件设计程序设计程序流程图程序解析 下载验证 SD 卡实验SD 卡简介SD 物理结构命令和响应卡模式数据模式 SDIO 接口简介SDIO 主要功能及框图SDIO 的时钟SDIO 的命令…

《程序员必备品质》——沉稳1

目录 前言&#xff1a; 一.言论有分寸 1.1不抱怨不指责 1.2谈话时不触及别人的短 1.3学会装聋作哑 二.沉心静气 2.1先稳定情绪再解决问题 2.2急于求成则遇速不达 三.结尾 前言&#xff1a; 这周&#xff0c;我细细的读了一本书&#xff0c;还没精读完&#xff0c;不过…

华为OD机试真题 JavaScript 实现【最多几个直角三角形】【2023Q1 100分】

一、题目描述 有 N 条线段&#xff0c;长度分别为 a[1]-a[n]。 现要求你计算这 N 条线段最多可以组合成几个直角三角形&#xff0c;每条线段只能使用一次&#xff0c;每个三角形包含三条线段。 二、输入描述 第一行输入一个正整数 T (1< T< 100) &#xff0c;表示有…

开源WebRTC库放大器模式在采集桌面图像时遇到的DPI缩放与内存泄漏问题排查

目录 1、在非100%的显示比例下放大器采集到的桌面图像不全问题 1.1、通过manifest文件禁止系统对软件进行缩放 1.2、调用SetThreadDpiAwarenessContext函数&#xff0c;禁止系统对目标线程中的窗口进行缩放 1.3、使用winver命令查看Windows的年月版本 2、使用放大器模式遇…

4年经验去面试21k测试岗,看到这样的面试题我还是心虚了....

我是着急忙慌的准备简历——4年软件测试经验&#xff0c;可独立测试大型产品项目&#xff0c;熟悉项目测试流程...薪资要求&#xff1f;4年测试经验起码能要个21K吧 我加班肝了一页半简历&#xff0c;投出去一周&#xff0c;面试电话倒是不少&#xff0c;自信满满去面试&#…

Highcharts for Python crack

Highcharts for Python crack   Aligned the API with Highcharts Core v11.1. In particular, this includes:   Added AccessibilityPoint.description_format property.   Added support for .legend_symbol to plot options and series options.   Added .border_…

6月10日两练来了!

今天是2023年6月10日&#xff0c;每日两练来了&#xff01; 一。围城 题目 编程星球上有一片100*100的空地&#xff0c;啊哈沃德在此处建立了N座发电站&#xff0c;每座发电站占地位置1*1格。 为了防止源码巨人的攻击&#xff0c;啊哈沃德需要在所有发电站外围修建电网&#x…

redis第九章-Redis队列Stream、Redis6多线程详解

Redis队列Stream 前置说明&#xff1a;Redis5.0 最大的新特性就是多出了一个数据结构 Stream&#xff0c;它是一个新的强大的支持多播的可持久化的消息队列&#xff0c;作者声明 Redis Stream 地借鉴了 Kafka 的设计。 Redis Stream 的结构如上图所示,每一个Stream都有一个消息…

【浅谈DBA 最重要的素质---读书笔记】

&#x1f448;【上一篇】 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 【下一篇】&#x1f449; &#x1f53b;【来自DBA大佬的见解1】 对于一个准备进入 DBA 领域的人&#xff0c;我希望他勤奋、严谨、具有钻研精神及独立思考能力。…

Android应用程序进程的启动过程

Android应用程序进程的启动过程 导语 到这篇文章为止&#xff0c;我们已经简要地了解过了Android系统的启动流程了&#xff0c;其中比较重要的内容有Zygote进程的启动和SystemService以及Launcher的启动&#xff0c;接下来我们将要学习的是Android应用程序的启动过程&#xff…