【数据结构】六、图:6.图的最短路径(BFS 算法、迪杰斯特拉(Dijkstra)算法、弗洛伊德(Floyd)算法)

news2024/11/26 4:54:05

3.最短路径

文章目录

    • 3.最短路径
      • 3.1 BFS 算法
      • 3.2 迪杰斯特拉(Dijkstra)算法
      • 3.3 弗洛伊德(Floyd)算法
      • 总结

在网图和非网图中,最短路径的含义是不同的。

由于非网图它没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径。

对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。

  • 单源最短路径
    • BFS(广度优先算法)算法(无权图)
    • 迪杰斯特拉(Dijkstra)算法(无权图、带权图)
  • 各个顶点之间的最短路径
    • 弗洛伊德(Floyd)算法(无权图、带权图)

3.1 BFS 算法

【技巧】不带权值图其实就是一直特殊的带权图,只是权值都是1。

通过一次遍历,就得到了每个结点到源点的距离。所以求最短路径的代码可以通过BFS遍历得到:

//BFS广度遍历算法求最短路径
void BFS_MIN_Distance(MGraph G, int v){
    Queue Q;
	InitQueue(&Q);	//初始化一辅助用的队列
    
    //d[i]表示从u到i结点的最短路径
    for(int i=0; i<G.numVertexes; ++i){
    	d[i] = 32767;	//初始化为无穷,意为不相连
    	path[i]=-1;		//最短路径从哪个顶点过来,就上这条路的上一个结点,这里是源点所以是-1
    }
    
//源点处理
    d[v]=0;		//结点本身,距离为0
    visit(v);	//访问顶点
    vivited[v]=TRUE;	//设置当前访问过
    EnQueue(&Q, v);	//将此顶点入队列

//BFS
    while(!QueueEmpty(Q)){
        DeQueue(&Q, &v);	//顶点i出队列
        for(w=FirstNeighbor(G, v); w>=0; w=NextNeighbor(G, v, w)){
            //检验v的所有邻接点
            if(!visited[w]){
                d[w]=d[v]+1	//路径长度+1
                path[w]=v;	//w的上一个结点是v
                visit(w);	//访问顶点w
                visited[w]=TRUE;	//访问标记
                EnQueue(Q, w);	//顶点w入队列
            }//if
        }//for
    }//while
}

3.2 迪杰斯特拉(Dijkstra)算法

Dijkstra算法[1]用于构建单源点的最短路径—,即图中某个点到任何其他点的距离都是最短的。例如,构建地图应用时查找自己的坐标离某个地标的最短距离。可以用于有向图,但是不能存在负权值。

6.4_3_最短路径问题_Dijkstra算法_哔哩哔哩_bilibili

在这里插入图片描述

在这里插入图片描述

【注意】Dijkstra算法不适用于有负权值的带权图

显然,Dijkstra算法也是基于贪心策略的。使用邻接矩阵或者带权的邻接表表示时,时间复杂度为O(|V|2)。

3.3 弗洛伊德(Floyd)算法

弗洛伊德(Floyd)算法是用来求任意两个结点之间的最短路的。

复杂度比较高,但是常数小,容易实现(只有三个 for)。

【适用】适用于任何图,不管有向无向,边权正负,但是最短路必须存在。(不能有个负环)

6.4_4_最短路径问题_Floyd算法_哔哩哔哩_bilibili

使用动态规划思想,将问题的求解分为多个阶段

对于n个顶点的图G,求任意一对顶点Vi -> Vj之间的最短路径可分为如下几个阶段:

  • 初始︰不允许在其他顶点中转,最短路径是?
  • 0:若允许在Vo中转,最短路径是?
  • 1:若允许在Vo、V中转,最短路径是?
  • 2:若允许在Vo、V1、Vz中转,最短路径是?
  • n-1∶若允许在Vo、V1、V2…Vn-1中转,最短路径是?

在这里插入图片描述

例子:

在这里插入图片描述

  1. 初始化:方阵 A ( − 1 ) [ i ] [ j ] = a r c s [ i ] [ j ] A^{(-1)}[i][j]=arcs[i][j] A(1)[i][j]=arcs[i][j].

  2. 第一轮:将 V 0 V_0 V0作为中间顶点,对于所有顶点 { i , j } \{i,j\} {i,j},如果有 A − 1 [ i ] [ j ] > A − 1 [ i ] [ 0 ] + A − 1 [ 0 ] [ j ] A^{-1}[i][j]>A^{-1}[i][0]+A^{-1}[0][j] A1[i][j]>A1[i][0]+A1[0][j],则将 A − 1 [ i ] [ j ] A^{-1}[i][j] A1[i][j]更新为 A − 1 [ i ] [ 0 ] + A − 1 [ 0 ] [ j ] A^{-1}[i][0]+A^{-1}[0][j] A1[i][0]+A1[0][j].

    eg:有 A − 1 [ 2 ] [ 1 ] > A − 1 [ 2 ] [ 0 ] + A − 1 [ 0 ] [ 1 ] = 11 A^{-1}[2][1]>A^{-1}[2][0]+A^{-1}[0][1]=11 A1[2][1]>A1[2][0]+A1[0][1]=11,更新 A − 1 [ 2 ] [ 1 ] = 11 A^{-1}[2][1]=11 A1[2][1]=11,更新后的方阵标记为 A 0 A^0 A0

  3. 第二轮:将 V 1 V_1 V1作为中间顶点,继续监测全部顶点对 { i , j } \{i,j\} {i,j}.

    eg:有 A 0 [ 0 ] [ 2 ] > A 0 [ 0 ] [ 1 ] + A 0 [ 1 ] [ 2 ] = 10 A^{0}[0][2]>A^{0}[0][1]+A^{0}[1][2]=10 A0[0][2]>A0[0][1]+A0[1][2]=10,更新后的方阵标记为 A 1 A^1 A1

  4. 第三轮:将 V 2 V_2 V2作为中间顶点,继续监测全部顶点对 { i , j } \{i,j\} {i,j}.

    eg:有 A 1 [ 1 ] [ 0 ] > A 1 [ 1 ] [ 2 ] + A 1 [ 2 ] [ 0 ] = 9 A^{1}[1][0]>A^{1}[1][2]+A^{1}[2][0]=9 A1[1][0]>A1[1][2]+A1[2][0]=9,更新后的方阵标记为 A 2 A^2 A2

此时 A 2 A^2 A2中保存的就是任意顶点对的最短路径长度。

应用Floyd算法求所有顶点之间的最短路径长度的过程如下表所示:

在这里插入图片描述

从这个表中,可以发下一些规律:

在这里插入图片描述

可以看出,矩阵中,每一步中红线划掉的部分都不用考虑计算,只需要计算红线外的部分,节省了计算量。


但是代码很简单:

//......准备工作,根据图的信息初始化矩阵A和path (如上图)
for(int k=0; k<n ; k++){	//考虑以vk作为中转点
	for(int i=0; i<n; i++) {	//遍历整个矩阵,i为行号,j为列号
		for(int j=0; j<n; j++){
			if (A[i][j] > A[i][k]+A[k][j]){	//以vk为中转点的路径更短
                A[i][j] = A[i][k]+A[k][j];//更新最短路径长度
                path[i][j] = k;//中转点
            }
        }
    }
}

综上时间复杂度是O(N3),空间复杂度是O(N2)。

总结

在这里插入图片描述

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

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

相关文章

JAVA—集合框架

集合 大小可变 是存储数据的容器&#xff0c;本文是在学习过ArrayList集合后对于集合进行一个比较系统的学习&#xff0c;只要是对于Collection类和Map类的学习和案例实践。需要对于Stream流再进行加深学习和理解&#xff0c;功能比较强大和简洁。 目录 1.集合体系结构 &…

流程图语法Mermaid教程

在使用Markdown来编写博客的过程中&#xff0c;尤其是需要更醒目的逻辑说明时&#xff0c;就需要使用流程图。 既然CSDN官方推荐Mermaid作为流程图语法&#xff0c;那我也针对Mermaid来做一期教程。 在学习之前&#xff0c;先总结一下流程图的需求&#xff1a; 节点设置方向设…

好看的超清4K视频素材去哪里找?下载素材资源网站分享

在当前高清与4K视频素材盛行的时代&#xff0c;创作出色的视频内容离不开优质的超清4K视频素材。以下是一些宝藏网站&#xff0c;它们提供了丰富的4K视频素材&#xff0c;可以使您的视频创作更加引人注目。 蛙学网 蛙学网是获取高质量4K视频素材的首选之地。该网站详细标注了视…

lvs、集群

1.集群和分布式 当多个用户当用户访问一个服务器时&#xff0c;服务器server1可能就会崩&#xff0c;假如这时候我们新加一个服务器server2来缓解server1的压力&#xff0c;那么就需要一个调度器lvs来分配&#xff0c;所以现在就是用户的访问就需要通过调度器之后到达服务器&a…

期望薪资3k,面试官笑了但没说话

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

Linux系统编程(8)进程进阶

一、进程的执行 子进程被创建好后&#xff0c;就需要去执行它所该执行的功能&#xff0c;根据子进程需要做的事&#xff0c;将其分为两类&#xff1a; 1.子进程所做的事与父进程差不多&#xff0c;两者功能几乎一样 //子承父业 2.子进程所做的事和父进程做的事完全不同&…

随手记录第十四话 -- 在 Spring Boot 3.2.3 中使用 springdoc-openapi-starter-webmvc-ui

项目升级到JDK21后&#xff0c;SpringBoot版本也到了3.2.3&#xff0c;之前的Swagger-ui不在支持了&#xff0c;找了其他的一直忘记记录了&#xff0c;这里记录一下。 快捷目录 1.引言2.添加依赖3.配置类4.Java代码实现5.启动应用6.总结 1.引言 随着 Spring Boot 版本的更新&a…

一个C++模板有意思的小实验

看面经遇到一个C模板的问题&#xff0c;顺手做了下实验看看结果&#xff0c;觉得比较有意思就记录一下 我们一般用模板会把声明和定义放在一起(放在同一个头文件内)&#xff0c;那么如果我们在一个头文件内声明我们要使用的模板函数&#xff0c;并在另一个cpp文件内实现会怎么样…

HarmonyOS NEXT星河版零基础入门(2)

1.Scroll滚动容器-核心用法 1&#xff08;1&#xff09;.Scroll的核心用法 快速得到一个长度为5的数组 Array.from({length:5}) 代码&#xff1a; 这种是默认是竖向的 要是想要实现横向的 就得把Scroll里边的Column改为Row组件 并且把scrolllable设置为Horizontal横向 1&a…

Spring AI 更新:支持OpenAI的结构化输出,增强对JSON响应的支持

就在昨晚&#xff0c;Spring AI发了个比较重要的更新。由于最近OpenAI推出了结构化输出的功能&#xff0c;可确保 AI 生成的响应严格遵守预定义的 JSON 模式。此功能显着提高了人工智能生成内容在现实应用中的可靠性和可用性。Spring AI 紧随其后&#xff0c;现在也可以对OpenA…

如何在萤石云视频app转移设备

本文将详述如何在萤石云视频app转移设备 一&#xff0e; 注意事项 1. 若设备正在分享中,无法转移 2. 若设备已开通云存储等可以转移的增值服务&#xff0c;相应的服务也会转移&#xff1b;若开通了订阅服务将取消订阅服务&#xff0c;次月不再扣费续订 3. 转移设备时若设备…

【iOS】—— Runloop和多线程问题总结

Runloop和多线程问题总结 runloop总结1. runloop简介2. runloop的基本作用3. 获取runloop的流程4. runloop和线程的关系5. runloop中的Mode有几种以及作用6.runloop的事件源7. 讲一下source0和source18. runloop的六种观察者模式9. 针对定时器在滑动时停止工作的问题10. 如何解…

【pytorch学习】transforms的使用

1 ToTensor() 作用&#xff1a;将 PIL Image 类型或者 numpy.ndarray 类型转为 tensor 类型 实例&#xff1a; from torchvision import transforms from PIL import Imageimg_path "data/train/bees/17209602_fe5a5a746f.jpg" img Image.open(img_path)print(i…

[数据结构]-快速排序

学习快排的基础 不想自己推导时间复杂度或者了解随机化的合理性,可以忽视下面这一条. 推导时间复杂度的方法:主定理随机化算法—数学基础:概率统计 QuickSort 快速排序: 1962年,Tony Hoare发明了这种如此高效实用的强大排序算法 分治法的体现:Divide and Conquer原地排序,…

数据结构+二叉遍历算法的应用

一、问题描述 编写一个程序&#xff0c;先用二叉树表示一个简单算术表达式&#xff0c;树的每一个 结点包括一个运算符或运算数。在简单算术表达式中只包含、-、 *、/和一位正整数且格式正确(不包含括号)&#xff0c;并且要按照先乘除后 加减的原则构造二叉树。如图 7.35 所示…

QT5生成独立运行的exe文件

目录 1 生成独立运行的exe文件1.1 设置工程Release版本可执行文件存储路径1.2 将工程编译成Release版本 2 使用QT5自带的windeployqt拷贝软件运行依赖项3 将程序打包成一个独立的可执行软件exe4 解决QT5 This application failed to start because no Qt platform plugin could…

批量快递中问题件筛选技巧大揭秘

批量快递中问题件筛选技巧大揭秘&#xff1a;固乔快递查询助手的强大功能 在电商行业日益繁荣的今天&#xff0c;快递服务成为了连接商家与消费者的关键纽带。然而&#xff0c;随着订单量的激增&#xff0c;如何高效处理并筛选出快递中的问题件&#xff0c;成为了许多商家面临…

shuishusihui

互斥量 使用互斥量可以用于保护某些临界资源&#xff0c;同一时间只能有一个任务来使用它。 使用互斥量会引入其他问题&#xff0c;比如说优先级反转&#xff0c;于是提出了优先级继承等方法解决问题 任务通知 任务通知就是通知任务&#xff0c;前边都是多对多的关系&#xff0…

算法解析——双指针算法(3)数据匹配

欢迎来到博主的专栏——算法解析 博主ID&#xff1a;代码小豪 文章目录 LCR179、查找总价格为目标值的两个商品leetcode11——盛水最多的容器leetcode611——有效三角形的个数 我们前面已经盘点了两种双指针算法的使用场景&#xff0c;现在来看看最常见的一种。 通常&#xff0…

社交电商系统开发功能定制

社交电商系统开发功能定制是一项综合性的服务&#xff0c;它涉及到需求分析、界面设计、功能开发、系统测试以及上线后的持续维护。以下是社交电商系统开发中应考虑的关键功能点&#xff1a; 需求分析和规划&#xff1a;开发前&#xff0c;企业需要明确业务需求&#xff0c;包…