全源最短路径之弗洛伊德算法(C语言)

Floyd(弗洛伊德)算法

该算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包。
时间复杂度为 O(N^3)
空间复杂度为 O(N^2)
Floyd算法蕴涵了动态规划的思想,
简单说:从任意节点i到任意节点j的最短路径存在两种可能

  1. 直接从i到j
  2. i经过若干个节点k到j

所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

Floyd算法适用于APSP(All Pairs Shortest Paths,多源最短路径),是一种动态规划算法,稠密图效果最佳。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于Dijkstra算法
优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据。

算法代码如下:

void Floyd(AdjMatrix *G)
{int A[MaxVertices][MaxVertices],path[MaxVertices][MaxVertices];int i,j,k;//初始化for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){A[i][j]=G->Edge[i][j];path[i][j]=-1;}}
//三重循环,floyd算法核心for (k=0;k<G->numV;k++){for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){if (A[i][j]>A[i][k]+A[k][j]){A[i][j]=A[i][k]+A[k][j];path[i][j]=k;}}}}Dispath(A,path,G->numV);//输出函数
}

输出函数包括两部分

void Ppath(int path[][MaxVertices],int i,int j)
{int k;k=path[i][j];if (k==-1){return;}Ppath(path,i,k);printf("%d->",k);Ppath(path,k,j);
}void Dispath(int A[][MaxVertices],int path[][MaxVertices],int n)
{int i,j;for (i=0;i<n;i++){for (j=0;j<n;j++){if (A[i][j]==INF){if (i!=j){printf("从%d%d没有路径\n",i,j);}}else{printf("  从%d%d的最短路径长度为:%d ",i,j,A[i][j]);printf("路径:%d->",i);Ppath(path,i,j);//两点i,j之间还有其他中继结点,则循环套用次函数printf("%d\n",j);}}}
}

具体代码如下:

#include<stdio.h>
#include<stdlib.h>
#define MaxVertices 100 //假设包含100个顶点
#define MaxWeight 32767 //不邻接时为32767,但输出时用 "∞"
#define MAXV 10
#define INF 32767
typedef struct{ //包含权的邻接矩阵的的定义char Vertices[MaxVertices];  //顶点信息的数组int Edge[MaxVertices][MaxVertices]; //边的权信息的数组int numV; //当前的顶点数int numE; //当前的边数
}AdjMatrix;void CreateGraph(AdjMatrix *G) //图的生成函数
{ int n,e,vi,vj,w,i,j;printf("请输入图的顶点数和边数(以空格分隔):");scanf("%d%d",&n,&e);G->numV=n;G->numE=e;for(i=0;i<n;i++) //图的初始化for(j=0;j<n;j++){ if(i==j)G->Edge[i][j]=0;else G->Edge[i][j]=32767;}for(i=0;i<n;i++)for(i=0;i<G->numV;i++) //将顶点存入数组中{ printf("请输入第%d个顶点的信息(整型):",i+1);  // G->adjlist[i].vertex=getchar(); scanf(" %c",&G->Vertices[i]);}printf("\n");for(i=0;i<G->numE;i++){ printf("请输入边的信息i,j,w(以空格分隔):");scanf("%d%d%d",&vi,&vj,&w); //若为不带权值的图,则w输入1//若为带权值的图,则w输入对应权值G->Edge[vi-1][vj-1]=w;//①G->Edge[vj-1][vi-1]=w;//②//无向图具有对称性的规律,通过①②实现//有向图不具备此性质,所以只需要①}
}
void DispGraph(AdjMatrix G) //输出邻接矩阵的信息
{ int i,j;printf("\n输出顶点的信息(整型):\n");for(i=0;i<G.numV;i++)printf("%8c",G.Vertices[i]);printf("\n输出邻接矩阵:\n");printf("\t");for(i=0;i<G.numV;i++)printf("%8c",G.Vertices[i]);for(i=0;i<G.numV;i++){ printf("\n%8d",i+1);for(j=0;j<G.numV;j++){ if(G.Edge[i][j]==32767) //两点之间无连接时权值为默认的32767,但输出时为了方便输出 "∞"printf("%8s", "∞");elseprintf("%8d",G.Edge[i][j]);}printf("\n");   }
}
void Ppath(int path[][MaxVertices],int i,int j)
{int k;k=path[i][j];if (k==-1){return;}Ppath(path,i,k);printf("%d->",k);Ppath(path,k,j);
}void Dispath(int A[][MaxVertices],int path[][MaxVertices],int n)
{int i,j;for (i=0;i<n;i++){for (j=0;j<n;j++){if (A[i][j]==INF){if (i!=j){printf("从%d到%d没有路径\n",i,j);}}else{printf("  从%d到%d的最短路径长度为:%d ",i,j,A[i][j]);printf("路径:%d->",i);Ppath(path,i,j);//两点i,j之间还有其他中继结点,则循环套用次函数printf("%d\n",j);}}}
}
void Floyd(AdjMatrix *G)
{int A[MaxVertices][MaxVertices],path[MaxVertices][MaxVertices];int i,j,k;//初始化for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){A[i][j]=G->Edge[i][j];path[i][j]=-1;}}
//三重循环,floyd算法核心for (k=0;k<G->numV;k++){for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){if (A[i][j]>A[i][k]+A[k][j]){A[i][j]=A[i][k]+A[k][j];path[i][j]=k;}}}}Dispath(A,path,G->numV);//输出函数
}int main()
{ AdjMatrix G;freopen("1.txt","r",stdin);CreateGraph(&G);Floyd(&G);DispGraph(G);
}

注:由于测试输入数据较多,程序可以采用文件输入
5 7
1
2
3
4
5
1 2 2
1 3 4
1 5 2
2 3 1
2 4 6
3 4 2
4 5 3

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

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

相关文章

Mybatis主线流程源码解析

Mybatis的基础使用以及与Spring的相关集成在官方文档都写的非常详细&#xff0c;但无论我们采用xml还是注解方式在使用的过程中经常会出现各种奇怪的问题&#xff0c;需要花费大量的时间解决。 抽空了解一下Mybatis的相关源码还是很有必要。 先来看一个简单的Demo&#xff1a; …

动态规划之背包问题(C语言)

动态规划 动态规划&#xff08;英语&#xff1a;Dynamic programming&#xff0c;简称DP&#xff09;是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题 动态规划思想大致上为&#xff1a;若要解一…

PHP函数-判断字符是否在于指定的字符串中

php中判断一个字符是否在字符串中 1、函数 以下四个函数都可以用来判断字符串中是否存在待查询的字符&#xff0c;可以是数字、字母或者符号。 strpos() - 查找字符串在另一字符串中第一次出现的位置&#xff08;区分大小写&#xff09; stripos() - 查找字符串在另一字符…

最大子列和问题(JAVA)

最大子列和 问题描述&#xff1a;给定N个整数的序列{A1&#xff0c;A2&#xff0c;A3&#xff0c;…&#xff0c;An}&#xff0c;求解子列和中最大的值。 这里我们给出{-2&#xff0c;11&#xff0c;-4&#xff0c;13&#xff0c;-5&#xff0c;-2}这样一个序列&#xff0c;正…

Oracle 11g必须开启的服务及服务详细介绍

成功安装Oracle 11g数据库后&#xff0c;你会发现自己电脑运行速度会变慢&#xff0c;配置较低的电脑甚至出现非常卡的状况&#xff0c;通过禁止非必须开启的Oracle服务可以提升电脑的运行速度。那么&#xff0c;具体该怎么做呢? 按照win7 64位环境下Oracle 11g R2安装详解中…

PHP—str_replace()替换函数的使用

一、str_replace()函数 1、定义和用法 str_replace() 函数替换字符串中的一些字符&#xff08;区分大小写&#xff09;。   注释&#xff1a;该函数是区分大小写的。请使用 str_ireplace() 函数执行不区分大小写的搜索。   注释&#xff1a;该函数是二进制安全的。 2、语…

JS/jQuery获取input的值和清空input的value值

一、获取input的值 1、通过普通选择器获取   通过类选择器获取&#xff1a;$(.class).val()   通过id选择器获取&#xff1a;$(" #id").val() 2、通过标签选择器获取   $(" input[ namename ] ").val()   $(" input[ typetext ] ").val…

JAVA刷题方法整理

JAVA刷题方法整理 一、String—>String[] 利用String.split()实现 注&#xff1a;在使用String.split 方法分隔字符串时&#xff0c;分隔符如果用到一些特殊字符&#xff0c;可能会得不到我们预期的结果&#xff0c;例如“|”&#xff0c;“*”&#xff0c;“”等&#x…

实现多线程Callable接口

Callable接口&#xff0c;实现多线程 1.实现 Callable接口&#xff0c;相较于实现 Runnable 接口的方式&#xff0c;优点是&#xff1a;方法可以有返回值&#xff0c;并且可以抛出异常 2.需要 FutureTask实现类的支持&#xff0c;用于接收运算结果 3.result.get()&#xff0c;接…

密码验证

用户在创建一个账户时&#xff0c;需要设置一个密码。密码的复杂程度是安全的保障之一&#xff0c;但是有些用户在设置密码时&#xff0c;总是把密码设置的过于简单&#xff0c;导致用户账户的安全存在威胁。因此&#xff0c;为了提高用户账户的安全性&#xff0c;添加了一个Ja…

阿里云windows/Linux 服务器建站教程,附WordPress配置方法

声明&#xff1a;文章仅供学习使用&#xff0c;故采用了多处链接&#xff0c;如有侵权&#xff0c;请私信我&#xff0c;立删。 最近看到一个学长做的验证界面&#xff0c;很简单的两个文本输入框&#xff0c;但是能给我们群里的小伙伴们做题提供一个验证答案的途径&#xff0…

Maven修改默认仓库为阿里云仓库

Maven 仓库默认在国外&#xff0c; 国内使用难免很慢&#xff0c;我们可以更换为阿里云的仓库。 第一步:修改 maven 根目录下的 conf 文件夹中的 setting.xml 文件&#xff0c;在 mirrors 节点上&#xff0c;添加内容如下&#xff1a; <mirrors><mirror><id>…

PHP语言结构详解

PHP语言结构 &#xff11;、语言结构释义   语言结构就是PHP语言的关键词&#xff0c;语言语法的一部分&#xff1b;   它不可以被用户定义或者添加到语言扩展或者库中&#xff1b;   它可以有也可以没有变量和返回值。 &#xff12;、为什么语言结构执行速度比函数快&…

查找算法——折半查找(JAVA)

折半查找 问题描述&#xff1a;给定一个整数X和整数A0&#xff0c;A1&#xff0c;A2……A(n-1)&#xff0c;后者已经预先排序并在内存中&#xff0c;求下标i使得Ai X &#xff0c;如果X不在数据中&#xff0c;则返回i -1。 我们首先可以想到的一种方法就是从左到右遍历&…

如何正确的检测对象类型?

在 javascript 中&#xff0c;我们常常用 typeof 运算符来检测对象的类型&#xff0c;在使用 typeof 检测引用类型的存储值会出现一个问题&#xff0c;无论引用的是什么类型的对象&#xff0c;它都会返回 "object"。这个时候我们往往会使用 instanceof instanceof 可…

PHP基于phpqrcode类生成二维码

使用ThinkPHP框架引入phpqrcode类生成二维码后&#xff0c;发现每次必须通过TP框架生成&#xff0c;略显繁琐&#xff0c;打算写一个简单的方法&#xff0c;然后运行php后直接批量生成二维码。方法也简单&#xff0c;直接写个PHP脚本&#xff0c;然后引入phpqrcode类&#xff0…

求最大公约数——欧几里得算法(JAVA)

欧几里得算法 问题描述&#xff1a;给出两个数m&#xff0c;n&#xff0c;求解这两个数的最大公因数 由于算法比较简单&#xff0c;这里不再赘述&#xff0c;我做的这个算法是默认了m>n,如果是对于任意两个数来说的话&#xff0c;我们这里还需要一个比较大小。 public cla…

编写函数digit(num, k),函数功能是:求整数num从右边开始的第k位数字的值,如果num位数不足k位则返回0。...

function digit(num,k){var knum 0;for(var i1; i<k; i){knum num%10;num parseInt(num/10);}return knum;}转载于:https://www.cnblogs.com/tis100204/p/10310140.html

JS/jQuery添加和移除CSS样式

有时候需要添加CSS样式和移除CSS样式&#xff0c;如添加display属性&#xff0c;设为隐藏。有时候需要移除display属性。 一、jQuery移除CSS样式的两种方法 注意&#xff1a;当其中一种不支持时&#xff0c;就尝试另一种&#xff1a; $("#show").removeAttr("…

高效幂运算(JAVA)--拆分解法、二进制解法

高效幂运算 问题描述&#xff1a;假设有一机器能够存储这样一些大整数&#xff08;或有一个编译程序能够模拟它&#xff09;&#xff0c;求一个相对大的数字&#xff08;一般为400位左右&#xff09;的极大幂&#xff08;400位左右&#xff09; 显然我们可以使用Java内置函数p…