算法设计与分析——Floyd算法(任意两点最短路径问题)

前言

关于最短路径的问题,我在上一篇文章《算法设计与分析——Dijkstra算法》中已经提到过了。但是,本篇我们需要讲解的Floyd算法,其解决的最短路径问题与Dijkstra算法有些许不同。
在《算法设计与分析——Dijkstra算法》中,我们就强调过,Dijkstra算法是一种单源点最短路径算法,什么是单源点最短路径算法?即在连通图中,我们从一个指定的点(这个就是源点)出发,寻找该点到连通图中其他所有点的最短路径及距离。而Floyd算法,其寻找的是连通图中任意一点到其他所有点的最短路径(我们讲解的过程中注重的是最短路径的距离,如果需要具体的路径,算法运行中做下记录即可),这是一个不同点。
再者,就是算法的核心思想问题,Dijkstra算法采用的是贪心算法(也称贪婪算法),即满足当前最优,以此来达到我最终结果的最优。Floyd算法则是利用的动态规划思想,利用子问题最优解,而来达到最终问题的最优解。二者有相似,但又不同。
那么,不废话了,接下来我们就来具体分析一下Floyd算法

一、算法思想分析

首先,我们来了解一下Floyd算法面对的问题:

  • 问题:给定一个加权连通图,要求找到从每个顶点到其他所有顶点之间的路径。

那么,Floyd算法是如何解决这个问题的呢?
接下来的内容可能有点绕,请大家慢慢阅读。
我们来想象一下,连通图中存在n个顶点,我们依次以这n个顶点作为中间点,什么是中间点?例如:a→b、b→c,如果我们要达成a→c的路径,这个时候b就是中间点。
在选好中间点后,就要开始构造最短路径了,我们的问题是什么?每个顶点到其他顶点之间的最短路径,那么我们肯定要遍历每个顶点到其他顶点吧?所以,选好中间点后,遍历每个点到其他顶点的路径(这里其实获取的是距离)。中间点这个时候的作用就体现到了,这个时候我们有一个选好的中间点,假设我们当前选到的中间点是c而我们当前遍历到的顶点路径是a→d,那么在这种情况下a→d所达成的最短路径距离就有两种构成,是之前已经记录过的a→d的最短路径(这个记录的最短路径,可能是我们利用前面的中间点获取到的zu),是a以c为中间点,然后抵达d的距离(即a→c,c→d的距离之和),这个就是当前情况下我们能够获取到的a→d的距离的两种方案,而要最短,即取二者最短存入即可。
上面是具体分析了一下,接下来我们简单总结一下:

  • 首先遍历所有点,将其作为中间点;
  • 在获取一个中间点后,开始分析每一个点到其他点的路径的情况,取最短路径距离为之前记录过的该点到另外一个点的最短距离和该点到中间点的最短路径距离加中间点到另外一个点的距离(有点像绕口令,希望大家能明白)中最短的那个。
  • 重复第二步操作,知道所有点都已经作为中间点,这个时候我们就获取到每一个顶点到另外一个点的最短路径(距离)。

再总结一下Floyd算法最短路径的计算公式:
Floyd总结
说句大白话就是,我到一个地方,我要么用以前的方法过去,要么我途径某个地方,再从这个地方到目的地。当然,这只是个比喻。
单独文字的话肯定过于枯燥,我们来举个《算法设计与分析基础》书中的栗子分析一下:
《算法设计与分析基础》例题分析
上图中表示连通图的方式是邻接矩阵的方式,第一个矩阵中0表示自己到自己,肯定距离为0,∞表示暂时不可达(不能直接抵达),其他数字则表示两点间的距离(路径权值)。
但是,我给出的C语言代码将会不一样,也就是矩阵定义的规则变了一下,其他仍然相通。

二、算法代码

C语言

我前面几篇文章都是算法效率分析在前,我觉得这样的顺序似乎有些问题,在本篇文章我先贴出代码,在写出算法效率分析,其效果可能会好一点。
对于接下来我给出的代码,我有一点有说明一下,我给出的邻接矩阵规则不一样,-1表示不可达,0表示自己到自己&#

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值