佛洛依德算法详解

2023-12-27 00:52
文章标签 算法 详解 佛洛依德

本文主要是介绍佛洛依德算法详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

佛洛依德算法详解

佛洛依德算法(Floyd-Warshall Algorithm)和迪杰斯特拉算法(Dijkstra’s Algorithm)都是用于解决图的最短路径问题的算法,但它们有一些关键的区别。

与迪杰斯特拉算法对比

佛洛依德算法:用于计算图中所有节点对之间的最短路径。
迪杰斯特拉算法:用于计算从一个源节点到其他所有节点的最短路径。

佛洛依德算法:具有较高的时间复杂度,通常为O(V^3),其中V是节点的数量。
迪杰斯特拉算法:在正常情况下,时间复杂度为O(V^2),但使用优先队列(堆)实现时可以优化到O((V+E)logV),其中E是边的数量。

佛洛依德算法:适用于稠密图,即边的数量相对较大的情况。
迪杰斯特拉算法:适用于稀疏图,即边的数量相对较小的情况。

佛洛依德算法:能够处理带有负权边的图。
迪杰斯特拉算法:对于带有负权边的图,可能会产生不正确的结果。

佛洛依德算法:基于动态规划,通过中间节点来更新路径。
迪杰斯特拉算法:基于贪心算法,每次选择当前最短路径的节点进行扩展。

总体而言,选择使用佛洛依德算法还是迪杰斯特拉算法取决于具体的问题和图的特性。如果图较小或者需要计算所有节点对之间的最短路径,可以考虑使用佛洛依德算法。如果图较大且只需计算从一个源节点到其他节点的最短路径,迪杰斯特拉算法可能更为高效。

存图

存图请参考上一篇介绍迪杰斯特拉算法的博客:https://blog.csdn.net/KK_2018/article/details/135198924

原理

设置一个dist数组,dist[i][j]表示从节点i到节点j的最短路径距离,dist先初始化,如果节点i到j存在直达路径,则将dist[i][j]初始化为路径值,否则初始化为无穷大(INF),然后依次将每个节点设置为从节点i到节点j的中间节点,如果加入中间节点会导致dist[i][j]变小,就更新dist[i][j]的值为这个更小的值,就核心原理就是一个公式:
d i s t [ i ] [ j ] = d i s t [ i ] [ j ] > d i s t [ i ] [ k ] + d i s t [ k ] [ j ] ? d i s t [ i ] [ k ] + d i s t [ k ] [ j ] : d i s t [ i ] [ j ] , i ≤ k ≤ j dist[i][j]=dist[i][j]>dist[i][k]+dist[k][j]?dist[i][k]+dist[k][j] : dist[i][j]\quad ,i\leq k\leq j dist[i][j]=dist[i][j]>dist[i][k]+dist[k][j]?dist[i][k]+dist[k][j]:dist[i][j],ikj

同时,我们还要设置一个二维数组next,来记录节点i到节点j路径上的i节点的下一个节点,例如路径为1–>2–>3–>4–>5,那么next[1][5]=2,next[2[5]=3,next[3][5]=4,next[4][5]=5,这样就可以把路径信息保存下来。

代码如下

// src表示源点,adjMatrix为保存图的邻接矩阵
void Graph::floyd(int src, std::vector<std::vector<int>>& dist, int adjMatrix[MAX][MAX])
{// 初始化一个二维向量 dist,用于存储所有节点之间的最短路径长度,初始值为无穷大(INF)dist = std::vector<std::vector<int>>(V, std::vector<int>(V, INF));// 将对角线上的元素设置为0,表示节点到自身的距离为0for (int i = 0; i < V; i++) {dist[i][i] = 0;}// 用于存储路径中下一个节点的信息std::vector<std::vector<int>> next(V, std::vector<int>(V, -1));for (int i = 0; i < V; i++)for (int j = 0; j < V; j++){if (i != j && adjMatrix[i][j] != INF) {// 复制邻接矩阵的初始值到 dist 中dist[i][j] = adjMatrix[i][j];next[i][j] = j; // 如果有连接边,设置下一个节点为目标节点 j}}// 在三重循环中进行动态规划,遍历所有节点 k,更新从节点 i 到节点 j 的最短路径for (int k = 0; k < V; k++){for (int i = 0; i < V; i++){for (int j = 0; j < V; j++){// 如果通过节点 k 能够获得更短的路径if (dist[i][k] + dist[k][j] < dist[i][j] && dist[i][k]!=INF && dist[k][j]!=INF){// 更新最短路径的值dist[i][j] = dist[i][k] + dist[k][j];// 更新路径中下一个节点的信息next[i][j] = next[i][k]; }}}}

那怎么把路径打印出来呢?也很简单,循环不断地求next[i][j]即可,代码如下

// src表示源点,dest表示目标节点
void Graph::saveFoPath(int src, int dest, std::vector<std::vector<int>>& next)
{std::vector<int> path;int current = src;while (current != dest) {path.push_back(current);current = next[current][dest];}path.push_back(dest);for (auto const& p : path){std::cout<<p<<' ';}std::cout<<endl;
}

这篇关于佛洛依德算法详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/541375

相关文章

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

前端高级CSS用法示例详解

《前端高级CSS用法示例详解》在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将深... 前端高级css用法在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义