当前位置: 首页 > news >正文

C语言-数据结构 弗洛伊德算法(Floyd)邻接矩阵存储

        弗洛伊德算法相比迪杰斯特拉相似的地方都是遍历邻接矩阵不断调整最短路径的信息,并且两种算法面对多源最短路径的时间复杂度都是O(n^3),Floyd采用的是动态规划而Dijkstra是采用贪心的思想。在Floyd中我们将创建两个数组进行辅助,一个path二维数组用于存储路径信息,一个table二维数组用于记录更新各结点间的最短路径长度,table的初始化就是简单的把邻接矩阵的信息复制过来,整个算法都是在这个table表中不断更新,代码中第一层for循环是控制中转结点,另外两行就是遍历整个table二位数组,table[v][k]表示辅助列,table[k][w]表示辅助行,辅助行与辅助列由中转结点控制在整个table表的主对角线上运动,table[v][w]当前扫描的邻接结点信息,如果当前邻接结点的权值大于对应的(辅助行+辅助列的权值和),那么说明找到更短的路径需要进行更新权值,当前邻接结点信息改为(辅助行+辅助列的权值和),同时更新路径信息为中转结点(即前驱顶点),代码中path[v][k]存储了对应的中转结点信息,利用它更新当前邻接结点的前驱结点(对应的中转结点)信息,当循环结束整个图各顶点到达其他所有顶点的最短距离就计算完成了,最后我们打印table矩阵的上三角部分因为两个结点的表示可以用一个方向就行,例如A->F打印了就可以表示F->A,并不需求遍历完全部table矩阵信息,同时打印路径信息的第二个for循环有个+1操作是为了避免打印AA、BB这种自己到自己的路径,也就是不打印主对角线,path路径信息的存储也同样用到并查集的部分思想在上一篇博文提过,在代码中通过不断循环path路径能够找到它的前驱结点一步步把所有路径结点信息找到,相比迪杰斯特拉倒着找结点信息,这里我们可以之间通过path二维数组顺序查找到路径信息,也是非常巧妙的!

 我们将创建下面的无向权值图:

84ef03cba4ba478383b338ae5884012a.png

  邻接矩阵的绘制还是手动赋值上三角,并通过矩阵对称性生成整个邻接矩阵,其中最小生成树中需要用到权值,对应原本有边的地方之前我是用1表示,现在改成边对应的权值,之前的0表示没有边,现在改成99表示为无穷,其实应该换成更大的值以确保树的边权值都小于这个最大值,但为了方便对齐显示看邻接矩阵,就使用了比本图中各边长较大的99来表示最大值。

9eefaa5c866742cbb239f5f9de2aff7d.png

Floyd算法代码:

//存储所有顶点的路径信息
typedef int Patharc[MAXVEX][MAXVEX];
//最短路径表copy邻接矩阵,不断扫描更新各顶点相互间的最短距离
typedef int ShortestPathTable[MAXVEX][MAXVEX];
// Floyd算法实现
void Floyd(MGraph G, Patharc path, ShortestPathTable table) {int v, w, k;// 初始化表和路径矩阵for (v = 0; v < G.numNodes; v++) {for (w = 0; w < G.numNodes; w++) {table[v][w] = G.arc[v][w];  // 初始化最短路径表if (G.arc[v][w] < INFINITY) {path[v][w] = w;  // 有直接边时,路径是目标顶点}else {path[v][w] = -1; // 如果没有边,则设为 -1}}}// Floyd算法的核心计算for (k = 0; k < G.numNodes; k++) {  // 遍历每个顶点作为中间顶点for (v = 0; v < G.numNodes; v++) {  // 遍历起点for (w = 0; w < G.numNodes; w++) {  // 遍历终点// 如果通过顶点 k 的路径更短,则更新路径和最短路径表if (table[v][w] > table[v][k] + table[k][w]) {table[v][w] = table[v][k] + table[k][w];path[v][w] = path[v][k];}}}}// 打印各顶点间的最短路径printf("各顶点间最短路径如下:\n");for (v = 0; v < G.numNodes; v++) {for (w = v + 1; w < G.numNodes; w++) {  // 遍历每对顶点//Array数组存储顶点ABCDEFGHprintf("%c-%c weight:%d\n", Array[v], Array[w], table[v][w]);k = path[v][w];  // 从起点到终点的路径printf("path:%d", v);while (k != w) {  // 路径输出printf("->%d", k);k = path[k][w];}printf("->%d\n", w);}printf("\n");}
}

完整代码(包括邻接矩阵的创建、Floyd算法)

#include "stdio.h"    
#include "stdlib.h"   
#include "math.h"  
#include "time.h"// 禁用特定的警告
#pragma warning(disable:4996)// 定义一些常量和数据类型
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXVEX 8 /* 最大顶点数,用户定义 */
#define MAXEDGE 10 /* 最大边数,用户定义 */
#define GRAPH_INFINITY 99 /* 用0表示∞,表示不存在边 *//* 定义状态、顶点和边的类型 */
typedef int Status;  /* Status是函数的返回类型,如OK表示成功 */
typedef char VertexType; /* 顶点的类型,用字符表示 */
typedef int EdgeType; /* 边上的权值类型,用整数表示 */
typedef int Boolean; /* 布尔类型 */
// 定义顶点标签
char Array[] = "ABCDEFGHI";/* 图的邻接矩阵结构体 */
typedef struct
{VertexType vexs[MAXVEX]; /* 顶点表 */EdgeType arc[MAXVEX][MAXVEX]; /* 邻接矩阵,表示边的权值 */int numNodes, numEdges; /* 图中当前的顶点数和边数 */
} MGraph;//存储所有顶点的路径信息
typedef int Patharc[MAXVEX][MAXVEX];
//最短路径表copy邻接矩阵,不断扫描更新各顶点相互间的最短距离
typedef int ShortestPathTable[MAXVEX][MAXVEX];/* 创建一个无向网图的邻接矩阵表示 */
void CreateMGraph(MGraph* G)
{int i, j, k, w;// 初始化图的顶点数和边数G->numNodes = 8;G->numEdges = 10;// 初始化邻接矩阵和顶点表for (i = 0; i < G->numNodes; i++) {for (j = 0; j < G->numNodes; j++) {G->arc[i][j] = GRAPH_INFINITY; /* 初始化邻接矩阵为∞ */}G->vexs[i] = Array[i]; /* 初始化顶点表 */}G->arc[0][0] = GRAPH_INFINITY;G->arc[0][1] = 10;G->arc[0][2] = GRAPH_INFINITY;G->arc[0][3] = GRAPH_INFINITY;G->arc[0][4] = GRAPH_INFINITY;G->arc[0][5] = 11;G->arc[0][6] = GRAPH_INFINITY;G->arc[0][7] = GRAPH_INFINITY;G->arc[1][0] = GRAPH_INFINITY;G->arc[1][1] = GRAPH_INFINITY;G->arc[1][2] = 23;G->arc[1][3] = GRAPH_INFINITY;G->arc[1][4] = GRAPH_INFINITY;G->arc[1][5] = GRAPH_INFINITY;G->arc[1][6] = 12;G->arc[1][7] = GRAPH_INFINITY;G->arc[2][0] = GRAPH_INFINITY;G->arc[2][1] = GRAPH_INFINITY;G->arc[2][2] = GRAPH_INFINITY;G->arc[2][3] = 21;G->arc[2][4] = GRAPH_INFINITY;G->arc[2][5] = GRAPH_INFINITY;G->arc[2][6] = GRAPH_INFINITY;G->arc[2][7] = GRAPH_INFINITY;G->arc[3][0] = GRAPH_INFINITY;G->arc[3][1] = GRAPH_INFINITY;G->arc[3][2] = GRAPH_INFINITY;G->arc[3][3] = GRAPH_INFINITY;G->arc[3][4] = GRAPH_INFINITY;G->arc[3][5] = GRAPH_INFINITY;G->arc[3][6] = GRAPH_INFINITY;G->arc[3][7] = 11;G->arc[4][0] = GRAPH_INFINITY;G->arc[4][1] = GRAPH_INFINITY;G->arc[4][2] = GRAPH_INFINITY;G->arc[4][3] = GRAPH_INFINITY;G->arc[4][4] = GRAPH_INFINITY;G->arc[4][5] = 47;G->arc[4][6] = GRAPH_INFINITY;G->arc[4][7] = 80;G->arc[5][0] = GRAPH_INFINITY;G->arc[5][1] = GRAPH_INFINITY;G->arc[5][2] = GRAPH_INFINITY;G->arc[5][3] = GRAPH_INFINITY;G->arc[5][4] = GRAPH_INFINITY;G->arc[5][5] = GRAPH_INFINITY;G->arc[5][6] = 6;G->arc[5][7] = GRAPH_INFINITY;G->arc[6][0] = GRAPH_INFINITY;G->arc[6][1] = GRAPH_INFINITY;G->arc[6][2] = GRAPH_INFINITY;G->arc[6][3] = GRAPH_INFINITY;G->arc[6][4] = GRAPH_INFINITY;G->arc[6][5] = GRAPH_INFINITY;G->arc[6][6] = GRAPH_INFINITY;G->arc[6][7] = 8;G->arc[7][0] = GRAPH_INFINITY;G->arc[7][1] = GRAPH_INFINITY;G->arc[7][2] = GRAPH_INFINITY;G->arc[7][3] = GRAPH_INFINITY;G->arc[7][4] = GRAPH_INFINITY;G->arc[7][5] = GRAPH_INFINITY;G->arc[7][6] = GRAPH_INFINITY;G->arc[7][7] = GRAPH_INFINITY;// 由于是无向图,邻接矩阵是对称的,需要将其对称for (int i = 0; i < G->numNodes; i++) {for (int j = 0; j < G->numNodes; j++) {G->arc[j][i] = G->arc[i][j];}}// 打印邻接矩阵printf("邻接矩阵为:\n");printf("     ");for (int i = 0; i < G->numNodes; i++) {printf("%2d ", i); /* 打印列索引 */}printf("\n     ");for (int i = 0; i < G->numNodes; i++) {printf("%2c ", G->vexs[i]); /* 打印顶点标签 */}printf("\n");for (int i = 0; i < G->numNodes; i++) {printf("%2d", i); /* 打印行索引 */printf("%2c ", G->vexs[i]); /* 打印顶点标签 */for (int j = 0; j < G->numNodes; j++) {if (G->arc[i][j] != 99) {printf("\033[31m%02d \033[0m", G->arc[i][j]); /* 打印邻接矩阵中的权值 */}else {printf("%02d ", G->arc[i][j]); /* 打印邻接矩阵中的权值 */}}printf("\n");}
}// Floyd算法实现
void Floyd(MGraph G, Patharc path, ShortestPathTable table) {int v, w, k;// 初始化表和路径矩阵for (v = 0; v < G.numNodes; v++) {for (w = 0; w < G.numNodes; w++) {table[v][w] = G.arc[v][w];  // 初始化最短路径表if (G.arc[v][w] < INFINITY) {path[v][w] = w;  // 有直接边时,路径是目标顶点}else {path[v][w] = -1; // 如果没有边,则设为 -1}}}// Floyd算法的核心计算for (k = 0; k < G.numNodes; k++) {  // 遍历每个顶点作为中间顶点for (v = 0; v < G.numNodes; v++) {  // 遍历起点for (w = 0; w < G.numNodes; w++) {  // 遍历终点// 如果通过顶点 k 的路径更短,则更新路径和最短路径表if (table[v][w] > table[v][k] + table[k][w]) {table[v][w] = table[v][k] + table[k][w];path[v][w] = path[v][k];}}}}// 打印各顶点间的最短路径printf("\n各顶点间最短路径如下:\n");for (v = 0; v < G.numNodes; v++) {for (w = v + 1; w < G.numNodes; w++) {  // 遍历每对顶点//Array数组存储顶点ABCDEFGHprintf("%c-%c weight:%d\n", Array[v], Array[w], table[v][w]);k = path[v][w];  // 从起点到终点的路径printf("path:%d", v);while (k != w) {  // 路径输出printf("->%d", k);k = path[k][w];}printf("->%d\n", w);}printf("\n");}
}// 主函数
int main(void) {MGraph G;/* 创建图 */CreateMGraph(&G);  // 创建并初始化图 GPatharc path;ShortestPathTable table;Floyd(G, path, table);  // 计算最短路径return 0;
}

 无向权值图:

84ef03cba4ba478383b338ae5884012a.png

运行结果:

相关文章:

C语言-数据结构 弗洛伊德算法(Floyd)邻接矩阵存储

弗洛伊德算法相比迪杰斯特拉相似的地方都是遍历邻接矩阵不断调整最短路径的信息&#xff0c;并且两种算法面对多源最短路径的时间复杂度都是O(n^3)&#xff0c;Floyd采用的是动态规划而Dijkstra是采用贪心的思想。在Floyd中我们将创建两个数组进行辅助&#xff0c;一个path二维…...

pyspark 安装记录

1、安装软件 1、python 3.10 2、hadoop-3.3.4 里面的winutils 要记得添加 3、java-17 4、spark-3.5.1-bin-hadoop3 python 安装 pyspark,Jupyter notebook pip install pyspark pip install jupyter notebook 2、添加环境变量 JAVA_HOME=C:\PySparkService\java-17H…...

高度可定制的电竞鼠标,雷柏VT1 PRO MAX体验

不管是菜鸟还是老鸟&#xff0c;游戏玩到某个阶段很容易出现瓶颈&#xff0c;在游戏的某个阶段&#xff0c;这里面制约最大的除了操作之外&#xff0c;实际上还是我们用的硬件。比如在PC游戏中&#xff0c;鼠标的影响就非常大&#xff0c;像是在游戏中如果鼠标延迟过高&#xf…...

经验笔记:SOA(面向服务的架构)

SOA&#xff08;面向服务的架构&#xff09;经验笔记 引言 SOA&#xff08;Service-Oriented Architecture, 面向服务的架构&#xff09;是一种设计原则&#xff0c;用于构建灵活且可扩展的分布式系统。SOA强调将应用程序的不同功能封装为独立的服务&#xff0c;这些服务通过…...

triton之ttir学习

一 基本语句 1 常量 %cst arith.constant dense<520192> : tensor<4096xi32> %c127_i32 arith.constant 127 : i32 %cst arith.constant dense<520192> : tensor<4096xi32> 解释&#xff1a;这条语句定义了一个名为 %cst 的常量&#xff0c;它…...

如何在AWS账户上进行充值:一份详尽指南

大家好&#xff0c;小编今天给大家带来一份关于如何在AWS账户上进行充值的详尽指南。对于使用AWS服务的用户来说&#xff0c;保持账户余额充足是确保服务不中断的关键。下面&#xff0c;九河云将详细讲解具体的操作步骤。 步骤一&#xff1a;登录AWS管理控制台 首先&#xff…...

(六十四)第 10 章 内部排序(静态链表的插入排序)

示例代码 staticLinkList.h // 静态链表的插入排序实现头文件#ifndef STATIC_LINK_LIST_H #define STATIC_LINK_LIST_H#include "errorRecord.h"#define SIZE 100 #define NUM 8typedef int InfoType; typedef int KeyType;typedef struct {KeyType key;InfoType inf…...

appium历史版本地址链接

appium / Appium.app / Downloads — Bitbucket ios的appium界面图 链接: https://pan.baidu.com/s/1i8BRaZgQA3ImLUhKZjfhiA 提取码: 5c8b...

TCPIP网络编程(尹圣雨)UDP 轮流收发消息(windows)

端口号写的是 2345 客户端 #include <iostream> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib")using std::cout; using std::endl; using std::cin;int main() {WSADATA wsa;if (WSAStartup(MAKEWORD(2, 2), &wsa) ! 0){cout <<…...

【相机方案(2)】V4L2 支持相机图像直接进入GPU内存吗?DeepStream 确实可以将图像数据高效地放入GPU内存进行处理!

V4L2 支持相机图像直接进入GPU内存吗&#xff1f; V4L2&#xff08;Video4Linux Two&#xff09;是Linux内核中用于视频捕获和播放的API&#xff0c;它本身并不直接支持将相机捕获的图像数据直接拷贝到GPU内存而不经过CPU内存。V4L2主要关注于视频设备的控制、数据的捕获和播放…...

UEFI——PEI阶段

一、PEI介绍 Pre-EFI Initialization&#xff08;PEI&#xff09;在引导的早期被调用&#xff0c;仅利用CPU资源调用PEIM&#xff0c;这些PEIM负责&#xff1a; &#xff08;1&#xff09;初始化一些永久内存 &#xff08;2&#xff09;在HOBs中描述内存信息 &#xff08;3…...

Nacos下载和启动

Nacos是什么&#xff1f; 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台 下载 https://github.com/alibaba/nacos/releases/tag/2.1.1启动 将下载好的Nacos解压缩&#xff0c;然后到bin目录下打开cmd 输入指令&#xff1a;startup.cmd -m standalone 出…...

怎么选择适合的服务器

大家都知道&#xff0c;不管是公司还是个人&#xff0c;在数字化浪潮已经席卷全球的环境下&#xff0c;大家对服务器的需求是日渐增长的。很多人在买服务器的时候&#xff0c;多少都有点选择困难&#xff0c;今天我们就来对比下物理服务器和弹性云服务器&#xff0c;看看选哪个…...

通义千问大模型Java调用,百炼

文章目录 一、大模型服务平台[百炼](https://help.aliyun.com/zh/model-studio/getting-started)二、Java sdk调用与eventStream三、百炼平台其它 一、大模型服务平台百炼 百炼是阿里新出的一个大模型服务平台&#xff0c;聚合了多个千问大模型及其它一些大模型的调用&#xf…...

新发现!一键管理所有远程会话的神器——1Remote

大家好&#xff0c;今天给大家介绍一款非常实用的工具——1Remote&#xff0c;这是一款现代化的个人远程会话管理器与启动器&#xff0c;让您的远程工作变得更加轻松高效&#xff01; 项目介绍 &#x1f680; 核心功能概览 多协议支持&#xff1a;1Remote支持RDP、SSH、VNC、…...

华为 HCIP 认证费用和报名资格

在当今竞争激烈的信息技术领域&#xff0c;华为 HCIP认证备受关注。它不仅能提升个人的技术实力与职业竞争力&#xff0c;也为企业选拔优秀人才提供了重要依据。以下将详细介绍华为 HCIP 认证的费用和报名资格。 一、HCIP 认证费用 华为HCIP认证的费用主要由考试费和培训费构成…...

Linux下载压缩包:tar.gz、zip、tar.bz2格式全攻略

在 Linux 中&#xff0c;下载各种格式的压缩包&#xff08;如 .tar.gz、.zip、.tar.bz2 等&#xff09;通常使用命令行工具如 wget 和 curl。 1. 使用 wget 下载压缩包 wget 是 Linux 中最常用的文件下载工具&#xff0c;支持 HTTP、HTTPS、FTP 等协议&#xff0c;可以直接从…...

运行PaddleOCR报错:requests.exceptions.SSLError: HTTPSconnectionPool……

文章目录 问题描述解决方法 问题描述 在运行以下代码时报错&#xff1a; ocr PaddleOCR(lang"en")解决方法 打开cmd&#xff0c;输入以下命令&#xff0c;查找Python解释器所在路径。 找到 Lib\site-packages\paddleocr\ppocr\utils\network.py&#xff0c;将代码…...

基于STM32L431小熊派设计的智能花盆(微信小程序+腾讯云IOT)(223)

文章目录 一、前言1.1 项目介绍【1】项目背景【2】设计实现的功能【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】ESP8266工作模式配置1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 系统框架图…...

CentOS 入门必备基础知识

CentOS&#xff08;Community ENTerprise Operating System&#xff09;是一个基于Red Hat Enterprise Linux&#xff08;RHEL&#xff09;的免费开源操作系统&#xff0c;广泛用于服务器环境。它以其稳定性、安全性和社区支持而闻名&#xff0c;对于初学者来说掌握一些基础知识…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...