Floyd算法图解,C++实现Floyd算法

news2024/9/25 5:21:29

Floyd算法简介

Floyd算法是一种多源最短路径算法,是利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
时间复杂度:O(n^3)。
空间复杂度:O(n^2)。

以另一篇Dijkstra算法的地图为例:https://blog.csdn.net/weixin_40355471/article/details/130655729?spm=1001.2014.3001.5502

数据结构抽象

Floyd是多源最短路径算法,一次计算可以算出所有顶点到其他任意顶点的最短路径,本例计算图1景点地图的最短路径。

在这里插入图片描述
初始化权重矩阵weitMatrix[][],如果从顶点 i 到顶点 j 有边,则weitMatrix[i][j] == <i,j>的权值,否则weitMatrix[i][j] == (无穷大),如图2。

在这里插入图片描述
初始化路径矩阵pathMatrix[][],初值为各个边的终点顶点的下标,如图3。
在这里插入图片描述

开始计算

初始状态
权重矩阵weitMatrix[][]如图2,初始两个点之间有边,则这两个点之间是连通的,如果没有边直接相连则是不通的。

Floyd算法的核心思想
选取任意一个点k,以k作为桥梁,寻找其他任意两个点i和j之间的更短路径,找到则更新权重矩阵和路径矩阵。

选取任意一个点

选取顶点1,以1作为中继,计算其他任意两点之间有没有更短路径。
借助顶点1,多了如下几条路径:
0->1->3(借道权重2+6 < 原权重∞,可以借道)
0->1->2(借道权重2+2 < 原权重5,可以借道)

一条条分析,借道权重 < 原权重时,更新权重矩阵和路径矩阵。
更新后的权重矩阵:
在这里插入图片描述
更新后的路径矩阵:
在这里插入图片描述

遍历所有点

重复上一步骤,直到遍历了所有顶点,得到最终的权重矩阵和路径矩阵。
最终的权重矩阵:
在这里插入图片描述
最终的路径矩阵:
在这里插入图片描述

计算最短路径

使用最终的权重矩阵和路径矩阵,如图6和图7,可计算任意两个顶点之间的最短路径。
示例:计算从顶点0到顶点4的最短路径:

1、先看权重矩阵,如果weitMatrix[0][4] = ∞,则表示没有路径可选,此路不通;否则表示有路径。
2、weitMatrix[0][4] = 5,表示有路径,且路径权重之和等于5。
3、看路径矩阵pathMatrix[0][4] = 1,表示从顶点1借道。
4、再看1->4,pathMatrix[1][4] = 2,表示从顶点2借道。
5、再看2->4,pathMatrix[2][4] = 4,说明从顶点可直接到终点4,得到完整的最短路径:0–>1–>2–>4。
6、其他任意两个顶点之间的最短路径均可以用这种方法计算。

C++实现Floyd算法

头文件

#ifndef FLOYD_H
#define FLOYD_H


#include<iostream>
#include<iomanip>
#include<string>
using namespace std;

#define MAX_WEIGHT 999//表示无穷
#define MAX_VERNUM 20//最大结点数

class Floyd//Adjacency Matrix Graph有向图,用邻接矩阵表示
{
public:
    Floyd(){};
public:
    void Create_graph();//创建图
    void Floyd_algo();//Floyd算法
    void print_path();//打印路径
    void ShowMatrix(int matrix[MAX_VERNUM][MAX_VERNUM]);//打印矩阵
private:
    int Vertexs[MAX_VERNUM];//顶点数组
    int weitMatrix[MAX_VERNUM][MAX_VERNUM];//权重矩阵
    int pathMatrix[MAX_VERNUM][MAX_VERNUM];//路径矩阵
    int VertexNum;//顶点数
    int EdgeNum;//边数
};

#endif // FLOYD_H

源文件

#include "Floyd.h"

int g_VertexNum = 5;
int g_EdgeNum = 8;
int g_edges[8][3] = {//边的集合
    //起点,终点,权值
    {0, 1, 2},
    {0, 2, 5},
    {1, 2, 2},
    {1, 3, 6},
    {2, 3, 7},
    {2, 4, 1},
    {3, 2, 2},
    {3, 4, 4}
};

void Floyd::Create_graph()
{
    VertexNum = g_VertexNum;
    EdgeNum   = g_EdgeNum;
    //初始化顶点数组
    for (int i = 0; i < VertexNum; i++)
    {
        Vertexs[i] = i;
    }

    //初始化邻接矩阵,权重初始化为无穷大
    for (int i = 0; i < VertexNum; i++)
    {
        for (int j = 0; j < VertexNum; j++)
        {
            weitMatrix[i][j] = MAX_WEIGHT;
        }
    }

    //权重矩阵赋值
    for (int i = 0; i < EdgeNum; i++)
    {
        weitMatrix[g_edges[i][0]][g_edges[i][1]] = g_edges[i][2];
    }

    //初始化路径矩阵,初值为各个边的终点顶点的下标
    for (int i = 0; i < VertexNum; i++)
    {
        for (int j = 0; j < VertexNum; j++)
        {
            pathMatrix[i][j] = j;
        }
    }

    cout << "init weight matrix:" << endl;
    ShowMatrix(weitMatrix);

    cout << "init pathMatrix:" << endl;
    ShowMatrix(pathMatrix);

    return;
}

void Floyd::Floyd_algo()
{
    for (int k = 0; k < VertexNum; k++)
        for (int i = 0; i < VertexNum; i++)
            for (int j = 0; j < VertexNum; j++)
                //以k做为桥梁,寻找ij之间的更短路径,找到则更新
                if (weitMatrix[i][k] + weitMatrix[k][j] < weitMatrix[i][j])
                {
                    weitMatrix[i][j] = weitMatrix[i][k] + weitMatrix[k][j];//更新i->j路径权重和
                    pathMatrix[i][j] = pathMatrix[i][k];//i->j,经过k路径更短,先到k
                }

    //更改到自身距离为0
    for (int i = 0; i < VertexNum; i++)
        for (int j = 0; j < VertexNum; j++)
            if (i == j)
                weitMatrix[i][j] = 0;

    cout << "Floyd algo:" << endl;

    cout << "weight matrix:" << endl;
    ShowMatrix(weitMatrix);//打印权重矩阵

    cout << "path matrix:" << endl;
    ShowMatrix(pathMatrix);//打印路径矩阵
}

void Floyd::print_path()
{
    cout << "The shortest path between any two vertices:" << endl;
    int row = 0;
    int col = 0;
    int temp = 0;
    for (row = 0; row < VertexNum; row++)
    {
        for (col = 0; col < VertexNum; col++)
        {
            if(row == col)//忽略自己到自己
                continue;
            if (weitMatrix[row][col] != MAX_WEIGHT)
            {
                cout << "v" << to_string(row) << "---" << "v" << to_string(col) << " weight: " << weitMatrix[row][col] << " path: " << " v" << to_string(row);
                temp = pathMatrix[row][col];
                //循环输出途径的每条路径,直到终点。
                while (temp != col)
                {
                    cout << "-->" << "v" << to_string(temp);
                    temp = pathMatrix[temp][col];
                }
                cout << "-->" << "v" << to_string(col) << endl;
            }
        }
        cout << endl;
    }
}

void Floyd::ShowMatrix(int matrix[MAX_VERNUM][MAX_VERNUM])
{
    for (int i = 0; i < VertexNum; i++)
    {
        for (int j = 0; j < VertexNum; j++)
        {
            cout << setw(4) << matrix[i][j] << " ";
        }
        cout << endl;
    }
}

调用方法:

Floyd mFloyd;
mFloyd.Create_graph();
mFloyd.Floyd_algo();
mFloyd.print_path();

打印输出:

init weight matrix:
 999    2    5  999  999 
 999  999    2    6  999 
 999  999  999    7    1 
 999  999    2  999    4 
 999  999  999  999  999 
init pathMatrix:
   0    1    2    3    4 
   0    1    2    3    4 
   0    1    2    3    4 
   0    1    2    3    4 
   0    1    2    3    4 
Floyd algo:
weight matrix:
   0    2    4    8    5 
 999    0    2    6    3 
 999  999    0    7    1 
 999  999    2    0    3 
 999  999  999  999    0 
path matrix:
   0    1    1    1    1 
   0    1    2    3    2 
   0    1    3    3    4 
   0    1    2    2    2 
   0    1    2    3    4 

最短路径:

The shortest path between any two vertices:
v0---v1 weight: 2 path:  v0-->v1
v0---v2 weight: 4 path:  v0-->v1-->v2
v0---v3 weight: 8 path:  v0-->v1-->v3
v0---v4 weight: 5 path:  v0-->v1-->v2-->v4

v1---v2 weight: 2 path:  v1-->v2
v1---v3 weight: 6 path:  v1-->v3
v1---v4 weight: 3 path:  v1-->v2-->v4

v2---v3 weight: 7 path:  v2-->v3
v2---v4 weight: 1 path:  v2-->v4

v3---v2 weight: 2 path:  v3-->v2
v3---v4 weight: 3 path:  v3-->v2-->v4

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

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

相关文章

Python模块multiprocessing 实现多进程并发

简介 multiprocessing模块是Python标准库中提供的一个用于实现多进程编程的模块。它基于进程而不是线程&#xff0c;可以利用多核CPU的优势&#xff0c;提高程序的执行效率&#xff0c;同时也可以实现进程间通信和数据共享。 目录 1. 参数说明 1.1. Process&#xff08;控制进…

推荐系统初谈

文章目录 简介推荐系统与搜索引擎发展历史所属领域 推荐系统分类概览基于内容的推荐基于协同过滤的推荐基于内存的协同过滤基于模型的协同过滤基于矩阵分解的推荐 推荐系统的评价指标推荐系统存在的问题参考文献 简介 21年笔记迁移&#xff0c;主要介绍了推荐系统的定义、发展…

【IC设计】ICC1 workshop lab guide 学习笔记

文章目录 Lab1 Data Setup&Basic Flow1.1 Create a Milkyway library1.2 Load the Netlist,TLU,Constraints and Controls1.3 Basic Flow:Design Planning1.4 Bsic Flow:Placement1.5 Basic Flow:CTS1.6 Basic Flow:Routing Design Planning2.1 Load the Design2.2 Initial…

算法刷题-字符串-反转字符串II

简单的反转还不够&#xff0c;我要花式反转 541. 反转字符串II 力扣题目链接 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起, 每计数至 2k 个字符&#xff0c;就反转这 2k 个字符中的前 k 个字符。 如果剩余字符少于 k 个&#xff0c;则将剩余字符全部反转。 …

C++笔记之初始化线程的所有方法

code review! C笔记之初始化线程的所有方法 文章目录 C笔记之初始化线程的所有方法一.非类中初始化线程1.使用函数指针初始化线程2.lambda表达式初始化线程3.使用成员函数初始化线程4.使用函数对象(Functor)初始化线程5.使用std::bind绑定函数及其参数初始化线程 二.类中初始化…

滤波电容计算举例

例&#xff1a;输入电压220VAC&#xff0c;功率4W&#xff1b;要求输出电压波动不超过5%&#xff0c;试计算滤波电容容量。 解&#xff1a;&#xff08;1&#xff09;电容的储能公式为&#xff1a;Wc1/2CU^2 当电容充电到峰值电压&#xff08;即220x1.414310V&#xff09;时&am…

数仓的分层理论

一、简介 2021-4-25 11:04:16 数据仓库分层是数据仓库设计中非常重要的一个环节&#xff0c;一个好的分层设计可以极大地简化数据仓库的操作&#xff0c;提升使用体验。然需要注意的是&#xff0c;分层理论并不绝对&#xff0c;只是提供一种普适的指导思想和原则&#xff0c;…

[Spring Cloud]:Study Notes·壹

文章目录 摘要1 认识微服务1.1 单体架构与分布式架构1.2 分布式架构与微服务1.3 微服务架构 2 nacos2.1 什么是nacos2.2 nacos使用2.2.1 nacos使用逻辑2.2.2 启动下载好的nacos2.2.3 引入依赖2.2.4 各注册服务中配置nacos相关信息2.2.5 测试nacos注册成功 3 Ribbon负载均衡3.1 …

改进YOLO系列 | YOLOv5/v7 引入谷歌 Lion 优化器

论文地址:https://arxiv.org/pdf/2302.06675.pdf 代码地址:https://github.com/google/automl/tree/master/lion 我们提出了一种将算法发现作为程序搜索的方法,并将其应用于发现用于深度神经网络训练的优化算法。我们利用高效的搜索技术来探索一个无限且稀疏的程序空间。为了…

计算机视觉-语义分割: FCN DeepLab Unet

文章目录 1. 概要1.1 什么是语义分割1.2 语义分割作用1.3 全卷积网络1.4 反卷积1.5 上采样三种方式1.6 跳层结构 Skip Layer 2. FCN架构3. DeepLab-v13.1 改进点3.2 空洞卷积(Atrous/Dilated convolution) 4. U-Net参考 1. 概要 1.1 什么是语义分割 从像素水平上理解、识别图…

微信小程序——Echarts使用(保姆式教程)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

从入门到精通!MATLAB基础教程及常用工具箱介绍

文章目录 基础介绍MATLAB窗口介绍MATLAB基本语法变量和数组控制流语句函数的定义和调用绘图MATLAB常用工具箱统计工具箱&#xff08;Statistics Toolbox)控制系统工具箱&#xff08;Control System Toolbox&#xff09;信号处理工具箱&#xff08;Signal Processing Toolbox&am…

搭建TiDB负载均衡环境-HAproxy+KeepAlived实践

作者&#xff1a; 我是咖啡哥 原文来源&#xff1a; https://tidb.net/blog/8e8cca1d 前言 HAProxy 提供 TCP 协议下的负载均衡能力&#xff0c;TiDB 客户端通过连接 HAProxy 提供的浮动 IP 即可对数据进行操作&#xff0c;实现 TiDB Server 层的负载均衡。同时&#xff0c…

SOFA Weekly|SOFARPC 5.10.1 版本发布、Layotto 社区会议回顾与预告、社区本周贡献

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展 欢迎留言互动&#xff5e; SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&am…

pytorch搭建AlexNet网络实现花分类

pytorch搭建AlexNet网络实现花分类 一、AlexNet网络概述分析 二、数据集准备下载划分训练集和测试集 三、代码model.pytrain.pypredict.py 一、AlexNet网络 概述 使用Dropout的方式在网络正向传播过程中随机失活一部分神经元&#xff0c;以减少过拟合 分析 对其中的卷积层、…

SORT+yolov5多目标跟踪

SORT 是一种简单的在线实时多目标跟踪算法。要点为&#xff1a; &#xff08;1&#xff09;以 IoU 作为前后帧间目标关系度量指标&#xff1b; &#xff08;2&#xff09;利用卡尔曼滤波器预测当前位置&#xff1b; &#xff08;3&#xff09;通过匈牙利算法关联检测框到目标&a…

thingsboard安装使用教程

1、安装tb-postgres tb-postgres是ThingsBoard与PostgreSQL数据库的单实例。 拉取tb-postgres镜像 docker pull thingsboard/tb-postgres 创建tb-postgres容器 docker run -itd --name tb-postgres -p 9090:9090 -p 1883:1883 -p 5683:5683/udp -p 5685:5685/udp -p 5432:…

如何使用银行四要素API接口提高用户身份认证的安全性

银行四要素是指银行在开户、转账等行为中对客户身份的核实&#xff0c;包括姓名、身份证号、银行卡号和手机号码。为了满足客户实名认证的需求&#xff0c;我们开发了相应的API接口&#xff0c;方便第三方开发人员进行身份核实的操作。 API接口名称&#xff1a;银行四要素验证…

Grafana图表配置快速入门

1、Grafana图表配置快速入门 前面我们使用 Prometheus Grafana 实现了一个简单的 CPU 使用率变化图&#xff0c;但是这个图还有许多缺陷&#xff0c;例如&#xff1a; 左边栏的数值太小了无法调整&#xff0c;下面的图标信息无法定制化等等。 其实 Grafana 的功能是非常强大…

平面电磁波的反射与折射,极化滤波作用

目录 引言 反射定律和折射定律 反射系数和折射系数 平面电磁波在理想介质分界面上的全反射和全折射 全反射 全折射 极化滤波作用 平面电磁波在良导体上的反射与折射 引言 再复杂的电磁波我们都可以看作是很多平面电磁波的叠加 我们在前面介绍的时候&#xff0c;我们认…