当前位置: 首页 > 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;对于初学者来说掌握一些基础知识…...

快速排序

一&#xff1a;基本思想 任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;右 子序列中所有元素均大于基准值&#xff0c;然后最左右子序列重复该过程&#xff0c;直到所有元…...

钢琴灯有必要买很贵的吗?五款值得入手的护眼灯分享

钢琴灯有必要买很贵的吗&#xff1f;首先在这里先回答一下众多家长们提出问题&#xff0c;护眼灯钢琴灯并不是越贵越好&#xff01;护眼灯钢琴灯这种比较大的电器虽然在生产中的用材用料存在一定的成本&#xff0c;但是并不是价格越贵的会越好&#xff0c;价格并不是决定产品质…...

C和指针:指针

内存和地址 程序视角看内存是一个大的字节数组&#xff0c;每个字节包含8个位&#xff0c;可以存储无符号值0至255,或有符号值-128至127。 多个字节可以合成一个字&#xff0c;许多机器以字为单位存储整数&#xff0c;每个字一般由2个或4个字节组成。 由于它们包含了更多的位&…...

paddle 分类网络

1.PaddlePaddlle强化学习及PARL框架 参考1 参考2 CPU版本安装 2.1 2.x版本安装 首先在anaconda下创建虚拟环境&#xff1a;可参考【1】Anaconda安装超简洁教程&#xff0c;瞬间学会&#xff01; 飞桨安装链接【开始使用_飞桨-源于产业实践的开源深度学习平台】 2 安装 con…...

计算机网络408考研 2022

https://zhuanlan.zhihu.com/p/695446866 1 1 1SDN代表软件定义网络。它是一种网络架构&#xff0c;旨在通过将网络控制平面从数据转发平面分离出来&#xff0c;从而实现网络的灵活性和可编程性。在SDN中&#xff0c;网络管理员可以通过集中式控制器 来动态管理网络流量&…...

2023级JavaScript与jQuery

第三课&#xff1a;JavaScript对象编程 一.预习笔记 1.Date对象 对象创建&#xff1a;var myDatenew Date() 输出显示当前日期的标准时间 对象创建&#xff1a;var myDatenew Date(“2024/09/14”) 对象创建&#xff1a;var myDatenew Date(2024,9,14) 当前对象创建时&…...

【C++】————IO流

作者主页&#xff1a; 作​​​​​​者主页 本篇博客专栏&#xff1a;C 创作时间 &#xff1a;2024年9月9日 一、C语言的输入和输出 C语言中我们用到的最频繁的输入输出方式就是 scanf() 和 printf()。 scanf()&#xff1a;从标准输入设备&#xff08;键盘&#xff09;读…...

ESP8266连接到Blinker平台

ESP8266是一款常见的物联网开发板&#xff0c;因其支持WIFI且性能强大&#xff0c;收到了各类电子爱好者的喜爱&#xff0c;Blinker是一个非常适合初学者的物联网开发平台&#xff0c;借助Arduino开发环境&#xff0c;二者之间进行巧妙配合&#xff0c;很容易便可以完成物联网的…...

qwen2 VL 多模态图文模型;图像、视频使用案例

参考&#xff1a; https://huggingface.co/Qwen/Qwen2-VL-2B-Instruct 模型&#xff1a; export HF_ENDPOINThttps://hf-mirror.comhuggingface-cli download --resume-download --local-dir-use-symlinks False Qwen/Qwen2-VL-2B-Instruct --local-dir qwen2-vl安装&#x…...

ASPICE评估:汽车软件质量的守护神

随着汽车行业的快速发展&#xff0c;车载软件系统的复杂性和重要性日益凸显。为了确保汽车软件的质量和安全性&#xff0c; 汽车行业引入了ASPICE&#xff08;Automotive SPICE&#xff09;评估作为评价软件开发团队研发能力的重要工具。 本文将详细介绍ASPICE评估的概念、过…...