当前位置:首页>java>开启上帝视角!Floyd 算法:一行代码算尽全网关系

开启上帝视角!Floyd 算法:一行代码算尽全网关系

  • 2026-10-09 19:34:29
开启上帝视角!Floyd 算法:一行代码算尽全网关系

前言

前两篇文章中介绍了 BFS(地毯式搜索)和 Dijkstra(精明导航)。它们都有一个共同点:以自我为中心。

也就是说,这两种算法都是“单源”(Single-Source)的。它们只能算出:

  • 我 到张三的距离

  • 我 到李四的距离

  • ...

但在很多时候,作为研究者,我们想拥有“上帝视角”。我们不想只知道“某个主角”的社交圈,我们想瞬间知道这个圈子里,任意两个人(张三和李四、王五和赵六...)之间的最短路径。

这时候,如果你对全班 50 个人每个人都跑一遍 Dijkstra,代码会写得很累。

Floyd-Warshall 算法,它用一种极其“暴力”却优雅的方式,一次性填满整个网络的距离矩阵。


 1. 为什么要用 Floyd?(解决什么问题)

Floyd 算法解决的是 多源最短路径(All-Pairs Shortest Paths) 问题。

它的核心应用场景:

  1. 小团体全景分析:比如你要分析一个 20 人的恐怖分子核心小组,你需要知道他们内部任意两人的联络成本,从而找出最脆弱的环节。

  2. 网络直径与中心度:只要跑一次 Floyd,你就能得到一个完整的矩阵。

    • 看每一行的和 —>算出每个人的接近中心性。

    • 看矩阵里的最大值 —> 就是网络直径。

  3. 传递闭包:判断谁和谁是连通的,谁和谁是老死不相往来的。


 2. 核心逻辑:疯狂的“中转站”

Floyd 算法的原理非常有意思,它利用了动态规划的思想,但我们可以用一个“买机票”的例子来秒懂它。

核心思想:

“两点之间,直线不一定最短。如果找个中间人(中转站),会不会更近?”

算法步骤(三层循环的暴力美学):

想象我们有一个 N*N 的表格(矩阵),填满了所有人目前的直连距离。

  1. 第一轮尝试:

    假设所有人只能通过 1号成员(张三) 进行中转。

    • 系统会问:从 我 到 你,原本距离是 10。如果走“我 -> 张三 -> 你”,距离是 2+3=5。

    • 5 < 10,太棒了!把表格里的距离更新为 5。

    • 系统会检查表格里所有的点对,看看能不能蹭张三的“顺风车”来缩短距离。

  2. 第二轮尝试:

    假设所有人可以通过 2号成员(李四) 进行中转。

    • 注意:这时候大家已经利用过张三了。现在看看加上李四,能不能更短?

  3. 第 N 轮尝试:

    ...直到把所有人都当做“中转站”试了一遍。

公式的通俗解释


3. 结果怎么解读?(距离矩阵)

Floyd 算法跑完后,你得到不是一个数,而是一个 距离矩阵(Distance Matrix)。

假设有 A, B, C 三个人:

ABC
A038
B302
C820

解读:

  1. 对角线为 0:自己到自己的距离永远是 0。

  2. 查表即得:想知道 A 到 C 的距离?直接看第 1 行第 3 列 —>8。

  3. 不对称性:如果是有向图(比如微博关注),矩阵可能是不对称的(A 到 B 是 3,B 到 A 可能是无穷大)。


 4. 有什么缺点?(致命警告)

Floyd 算法是典型的“用时间换方便”。它的缺点非常非常明显,甚至可以说是致命的。

缺点一:慢到令人发指

  • 它的时间复杂度是 O(N^3)。这是什么概念?

    • 20 个节点:计算 20^3 = 8,000 次。秒出。

    • 100 个节点:计算 1,000,000 次。稍微等一下。

    • 1,000 个节点:计算 10 亿次。去喝杯咖啡吧。

    • 10,000 个节点:计算 1 万亿次。你的电脑会直接死机。

  • 警告:千万不要在大规模社交网络(如微博、Facebook)上跑 Floyd! 它是为小圈子分析而生的。

缺点二:空间占用大

它需要维护一个 N * N 的矩阵。如果是几万个节点,光存这个矩阵就能把内存撑爆。


 5. 总结与 Python 实战

Floyd 算法是小规模网络分析的“核武器”。

  • 什么时候用?

    • 节点数很少(< 500 个)。

    • 网络比较稠密(边很多,几乎大家都认识大家)。

    • 你需要一次性计算出全员两两之间的距离。

  • 什么时候别用?

    • 节点数 > 1000。请老老实实对每个节点循环跑 Dijkstra 或 BFS。

Python NetworkX 代码示例:

import networkx as nx# 1. 建图(小规模)G = nx.Graph()G.add_edges_from([(1, 2), (2, 3), (3, 4), (1, 4)])# 2. 开启上帝视角 (Floyd)# NetworkX 会自动帮你处理好矩阵计算all_pairs = nx.floyd_warshall(G)# 3. 查看结果print("节点1到节点3的最短距离:", all_pairs[1][3])# 输出结果应该是 2 (路径 1-2-3 或 1-4-3)

结语

至此,我们的“最短路径三剑客”(BFS、Dijkstra、Floyd)已经全部集结完毕。

  • BFS:查户口(数人头)。

  • Dijkstra:跑导航(省成本)。

  • Floyd:上帝视角(全图打击)。

更多内容,敬请关注

最新文章

随机文章