数据结构 —— FloydWarshall算法

数据结构 —— FloydWarshall算法

  • FloydWarshall算法
  • 三种最短路径算法比较
      • 1. Dijkstra算法
      • 2. Bellman-Ford算法
      • 3. Floyd-Warshall算法
      • 总结

我们之前介绍的两种最短路径算法都是单源最短路径,就是我们要指定一个起点来寻找最短路径,而我们今天介绍的FloydWarshall算法,可以不指定源点,找到最短路径:

FloydWarshall算法

在介绍FloydWarshall算法之前,我们先来想一个问题,就是:最短路径要经过多少顶点呢?
在这里插入图片描述第一种情况他俩之间就是最短距离
在这里插入图片描述
第二种,中间经过了许多结点
在这里插入图片描述在这里插入图片描述
Floyd-Warshall算法是一种在有向图中寻找所有顶点对之间的最短路径的算法。它可以在图中包含负权边的情况下工作,但是图中不能包含负权循环。

以下是Floyd-Warshall算法的基本步骤:

  1. 初始化:创建一个n×n的距离矩阵D,其中D[i][j]表示从顶点i到顶点j的最短路径的长度。如果(i,j)之间没有直接的边,则D[i][j]设置为无穷大。对于所有的顶点i,D[i][i]=0。
  1. 对于每一个中间顶点k,更新距离矩阵D。具体来说,对于每一对顶点(i, j),如果D[i][j] > D[i][k] + D[k][j],则更新D[i][j]为D[i][k] + D[k][j]。这相当于检查是否可以通过k作为中间顶点来获得从i到j的更短路径。
  1. 重复步骤2,直到所有可能的中间顶点都被考虑过。
  1. 最后,距离矩阵D中的每个元素D[i][j]将包含从顶点i到顶点j的最短路径的长度
void FloydWarshall(vector<vector<W>>& vvDest, vector<vector<int>>& vvParentpath)
{// 调整vvDest和vvParentpath的大小与顶点数量一致vvDest.resize(_vertex.size());vvParentpath.resize(_vertex.size());// 初始化距离矩阵为最大权重(表示不可达)// 初始化前驱节点矩阵为-1(表示无前驱节点)for (size_t i = 0; i < _vertex.size(); i++){vvDest[i].resize(_vertex.size(), MAX_W);vvParentpath[i].resize(_vertex.size(), -1);}// 初始化距离矩阵和前驱节点矩阵// 如果两个顶点间存在直接连接,则设置距离矩阵的相应位置为该连接的权重// 并且设置前驱节点为当前顶点for (size_t i = 0; i < _vertex.size(); i++){for (size_t j = 0; j < _vertex.size(); j++){// 同一顶点到自身的距离为0,前驱节点为-1if (i == j){vvDest[i][j] = 0;vvParentpath[i][j] = -1;}// 如果两顶点之间有直接连接,并且权重不是最大权重(即可达)if (_matrix[i][j] != MAX_W){vvDest[i][j] = _matrix[i][j];vvParentpath[i][j] = i;}else{// 如果两顶点之间不可达,前驱节点为-1vvParentpath[i][j] = -1;}}}// 这里是核心部分,遍历所有顶点作为中间顶点,以检查是否存在更短路径for (size_t k = 0; k < _vertex.size(); k++){for (size_t i = 0; i < _vertex.size(); i++){for (size_t j = 0; j < _vertex.size(); j++){// 如果存在通过顶点k作为中间顶点的更短路径,则更新距离和前驱节点if (vvDest[i][k] != MAX_W && vvDest[k][j] != MAX_W && vvDest[i][k] + vvDest[k][j] < vvDest[i][j]){vvDest[i][j] = vvDest[i][k] + vvDest[k][j];vvParentpath[i][j] = vvParentpath[k][j];}}}// 打印每次迭代后的距离矩阵和前驱节点矩阵(可选)//打印权值和路径矩阵观察数据//cout << "     ";//for (size_t i = 0; i < _vertex.size(); i++)//{//	cout << _vertex[i] << " ";//}//cout << endl;for (size_t i = 0; i < _vertex.size(); ++i){cout << _vertex[i] << " ";for (size_t j = 0; j < _vertex.size(); ++j){if (vvDest[i][j] == MAX_W){//cout << "*" << " ";printf("%3c", '*');}else{//cout << vvDest[i][j] << " ";printf("%3d", vvDest[i][j]);}}cout << endl;}cout << endl;for (size_t i = 0; i < _vertex.size(); ++i){for (size_t j = 0; j < _vertex.size(); ++j){//cout << vvParentPath[i][j] << " ";printf("%3d", vvParentpath[i][j]);}cout << endl;}cout << "=================================" << endl;}}
}

我们构建这样的图:
在这里插入图片描述

	void TestFloydWarshall(){const char* str = "12345";Graph<char, int, INT_MAX, true> g(str, strlen(str));g.AddEdge('1', '2', 3);g.AddEdge('1', '3', 8);g.AddEdge('1', '5', -4);g.AddEdge('2', '4', 1);g.AddEdge('2', '5', 7);g.AddEdge('3', '2', 4);g.AddEdge('4', '1', 2);g.AddEdge('4', '3', -5);g.AddEdge('5', '4', 6);vector<vector<int>> vvDist;vector<vector<int>> vvParentPath;g.FloydWarshall(vvDist, vvParentPath);}

在这里插入图片描述
大家可以对应一下上面的图,这里注意一下,我们的路径的数组存储的是下标,所以每组的第二个图比上图中的数值小1,这是正常的。

我们可以把每个结点到其他结点的最短路径打印出来:

	void TestFloydWarshall(){const char* str = "12345";Graph<char, int, INT_MAX, true> g(str, strlen(str));g.AddEdge('1', '2', 3);g.AddEdge('1', '3', 8);g.AddEdge('1', '5', -4);g.AddEdge('2', '4', 1);g.AddEdge('2', '5', 7);g.AddEdge('3', '2', 4);g.AddEdge('4', '1', 2);g.AddEdge('4', '3', -5);g.AddEdge('5', '4', 6);vector<vector<int>> vvDist;vector<vector<int>> vvParentPath;g.FloydWarshall(vvDist, vvParentPath);// 打印任意两点之间的最短路径for (size_t i = 0; i < strlen(str); ++i){g.PrintShortestPath(str[i], vvDist[i], vvParentPath[i]);cout << endl;}}

在这里插入图片描述
我们也可以把之前小潮的图拿出来测测:
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

三种最短路径算法比较

在图论中,寻找最短路径是常见的问题,有多种算法可以解决这个问题,包括Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法。下面是对这三种算法的比较:

1. Dijkstra算法

适用场景:适用于没有负权边的加权图,无论是有向还是无向图。

优点

  • 时间复杂度较低,使用优先队列优化后的时间复杂度为O((V+E)logV)。
  • 算法简单,易于理解和实现。

缺点

  • 不能处理含有负权边的图。

2. Bellman-Ford算法

适用场景:适用于任何加权图,包括含有负权边的图,但不能有负权回路。

优点

  • 可以检测并报告图中是否存在负权回路。
  • 对于稀疏图,性能优于Floyd-Warshall算法。

缺点

  • 时间复杂度较高,为O(VE),当E较大时效率低。
  • 每次迭代都需要更新所有边,即使某些边的最短路径已经确定。

3. Floyd-Warshall算法

适用场景:适用于任何加权图,包括含有负权边的图,但不能有负权回路。特别适合于求解所有顶点对之间的最短路径问题。

优点

  • 可以一次计算出所有顶点对的最短路径。
  • 算法简洁,易于理解。

缺点

  • 时间复杂度高,为O(V^3),对于大规模图的计算效率低下。
  • 需要额外的空间来存储中间结果,空间复杂度为O(V^2)。

总结

  • 如果只需要求解单源最短路径问题,且图中没有负权边Dijkstra算法是首选
  • 如果图中可能含有负权边,但没有负权回路,Bellman-Ford算法更为适用
  • 当需要求解所有顶点对之间的最短路径时,Floyd-Warshall算法是最直接的选择,尽管它的时间和空间复杂度较高

选择哪种算法取决于具体的问题背景和图的特性。

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

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

相关文章

ctfshow-web入门-文件上传(web166、web167)(web168-web170)免杀绕过

目录 1、web166 2、web167 3、web168 4、web169 5、web170 1、web166 查看源码&#xff0c;前端只让传 zip 上传 zip 成功后可以进行下载 随便搞一个压缩包&#xff0c;使用记事本编辑&#xff0c;在其内容里插入一句话木马&#xff1a; 上传该压缩包&#xff0c;上传成功…

附下载 | 100项能源领域网络与数据安全政策全集(2024版)

能源是工业的粮食&#xff0c;能源安全事关国家根本安全。当今国际局势风云变幻&#xff0c;全球地缘政治、经济、科技体系正经历深刻变化&#xff0c;能源局势将更加错综复杂&#xff0c;威胁能源安全的各种“灰犀牛”“黑天鹅”事件时有发生&#xff0c;促使国际能源版图深刻…

system V共享内存【Linux】

文章目录 原理shmgetftokshmat(share memory attach)shmdt&#xff0c;去关联&#xff08;share memory delete attach&#xff09;shmctl ,删除共享内存共享内存与管道 原理 共享内存本质让不同进程看到同一份资源。 申请共享内存&#xff1a; 1、操作系统在物理内存当中申请…

详解Redis:什么是Redis?

什么是Redis? Redis&#xff08;Remote Dictionary Server&#xff09;是一种开源的、高性能的、基于内存快速读写的的数据结构存储系统&#xff0c;常用于缓存&#xff0c;分布式锁等场景&#xff1b; Redis常用数据类型有哪些&#xff1f; String(字符串) 适用场景…

Qt中实现让静态图片动起来,创建动画效果

在现代应用程序开发中&#xff0c;动画效果是提升用户体验的重要元素之一。Qt作为一个强大的跨平台应用程序框架&#xff0c;提供了丰富的工具和库来创建各种动画效果。本文将介绍如何在Qt中使用静态图片创建动画效果。 实现方法一 使用QTimer和QPixmap 1.准备图片资源&#…

Qt图形与图片(Qt位置相关函数、Qt基础图形的绘制、双缓冲机制、显示SVG格式图片)

此篇文章介绍几种主要位置函数及其之间的区别&#xff0c;以及各种与位置相关函数的使用场合&#xff1b;然后&#xff0c;通过一个简单绘图工具实例&#xff0c;介绍利用QPainter和QPainterPath两种方法绘制各种基础图形&#xff1b;最后&#xff0c;通过几个实例介绍如何利用…

暑假自律日记十

7.11 &#xff08;半小时日记打卡之——暑假第十天&#xff09; 日程 8.30起床 9.20到达逸夫楼开始总结区间DP&#xff0c;上午完成了区间DP和四边形优化部分的学习 下午组队打了一场去年的牛客多校&#xff0c;压力有点大&#xff0c;问题也有点多&#xff0c;总而言之&…

GD32F303RET6读取SGM58031电压值

1、SGM58031芯片详解 &#xff08;1&#xff09;SGM58031是一款低功耗&#xff0c;16位精度&#xff0c;delta-sigma (ΔΣ)模数转换器(ADC)。它从3V到5.5V供电。 &#xff08;2&#xff09;SGM58031包含一个片上参考和振荡器。它有一个I2C兼容接口&#xff0c;可以选择四个I2…

深入Memcached键值对限制:优化存储策略

标题&#xff1a;深入Memcached键值对限制&#xff1a;优化存储策略 Memcached作为一种广泛使用的高性能分布式内存缓存系统&#xff0c;对键值对的大小有特定的限制。这些限制不仅关系到缓存效率&#xff0c;还直接影响到缓存数据的组织和内存的使用。本文将深入探讨Memcache…

【RHCE】系统服务综合实验

一、实验内容 现有主机 node01 和 node02&#xff0c;完成如下需求&#xff1a; 1、在 node01 主机上提供 DNS 和 WEB 服务 2、dns 服务提供本实验所有主机名解析 3、web服务提供 www.rhce.com 虚拟主机 4、该虚拟主机的documentroot目录在 /nfs/rhce 目录 5、该目录由 node02…

Python | Leetcode Python题解之第229题多数元素II

题目&#xff1a; 题解&#xff1a; class Solution:def majorityElement(self, nums: List[int]) -> List[int]:cnt {}ans []for v in nums:if v in cnt:cnt[v] 1else:cnt[v] 1for item in cnt.keys():if cnt[item] > len(nums)//3:ans.append(item)return ans

【conda】解决 An HTTP error occurred when trying to retrieve this URL.问题

1. 修改SSL验证 如果其他方法无效&#xff0c;还可以尝试关闭SSL验证来解决问题。具体操作如下&#xff1a; 在终端中输入以下命令&#xff0c;关闭SSL验证&#xff1a; conda config --set ssl_verify false或者&#xff0c;在conda的配置文件&#xff08;.condarc&#xff0…

为什么渲染农场渲染的是帧,而不是视频?

在3D动画产业的壮阔画卷中&#xff0c;渲染农场作为幕后英雄&#xff0c;以其庞大的计算能力支撑起无数视觉奇观的诞生。这些由高性能计算机集群构成的系统&#xff0c;通过独特的逐帧渲染策略&#xff0c;解锁了单机难以企及的创作自由与效率。本文将深入剖析这一策略背后的逻…

maven7——(重要,构建项目)maven项目构建(命令)

Maven的常用命令管理项目的生命周期 clean命令 清除编译产生的target文件夹内容&#xff0c;可以配合相应命令在cmd中使用&#xff0c;如mvn clean package&#xff0c; mvn clean test D:\工作\公司培训-4班\day20\day20\untitled1>mvn clean compile命令 该命令可以…

element如何实现自定义表头?

有时候我们需要实现自定义表头,例如表头里加按钮啥的,这时候就需要用到自定义表头,但是官方对自定义表头的使用写的还是比较简单,今天就来详细说说 在需要使用自定义表头的表头上使用:render-header来启用自定义表头: <el-table-column :render-header="button&…

机器学习开源分子生成系列(2)-基于三维形状和静电相似性的DeepFMPO v3D安装及使用

前言 本文是基于 3D 的分子生成方法DeepFMPO v3D的介绍及安装使用。 一、DeepFMPO v3D是什么&#xff1f; github代码介绍文章 在药物发现中&#xff0c;如何寻找具新颖性和结构多样性的候选分子是颇受药物设计科学家关注的问题。通过虚拟筛选的化学空间搜索往往会受限于筛选…

Linux账户和组管理——用户密码文件,工作组账号文件,用户管理

#### 用户密码文件 - /etc/shadow存储密码加密后的密文&#xff0c;又称为“影子文件”&#xff0c;该文件为了保证了账户密码的安全性只有 root 账户拥有读权限&#xff0c;注意&#xff1a;若该文件权限发生变化&#xff0c;需要留心恶意攻击 bash [rootserver ~]# ll /etc/…

linux之栈溢出分析

我们来创建一个例子&#xff0c;其中包含一个段错误&#xff0c;这次是由于栈溢出导致的。这是一个常见的错误&#xff0c;通常发生在程序递归调用深度过大&#xff0c;超出了为栈分配的内存空间。 下面是一个简单的C程序&#xff0c;stack_overflow_example.c&#xff0c;它通…

优化与改进之轻量级Transformer - Transformer教程

在自然语言处理&#xff08;NLP&#xff09;的世界里&#xff0c;Transformer模型无疑是一颗璀璨的明珠。自从它在2017年被提出以来&#xff0c;就凭借其强大的性能和优雅的设计赢得了广泛的关注和应用。然而&#xff0c;随着应用的深入&#xff0c;Transformer的体量和计算资源…

牛顿力学和拉格朗日力学求解atwood machine问题对比

一个半径为 R R R、转动惯量为 I I I 的圆盘。绳子与圆盘无滑动&#xff0c;质量 m 2 m_2 m2​ 的物体在重力 g g g 作用下下坠&#xff0c;带动质量 m 1 m_1 m1​ 的物体上升。求 m 1 m_1 m1​和 m 2 m_2 m2​ 的加速度 a a a。 牛顿力学方法 对质量 m 1 m_1 m1​ 和 …