再谈 dijkstra 算法和最短路径问题

前置文章:
dijkstra 算法为什么高效
有向图的负权值边与建模
求单源最短路径的新方法

前天晚上实现了一个基于 dijkstra 算法的求单源最短路径的新算法,整理了一篇文章。我非常不愿意把一些直观的问题太过于技术化,但多年的职业经历偏偏让一篇好好的文字写着写着就变成技术博客了,非常不适。

我的新算法强调 “只需要一次广度优先遍历”,文章 求单源最短路径的新方法 里的图解释得已经很明白了,但这和 dijkstra 算法有什么关系,为什么说是 “基于 dijkstra 算法的新算法”,基不基于不重要,要点在于,dijkstra 算法本身,它就是一个 “只需要一次广度优先遍历” 就获得结果的算法,不同点在于,dijkstra 算法用 S 到 V_curr 的距离来松弛,而我的方法则是用坐标系把每个节点的松弛结果都展示了出来,松弛的过程通过递归调整后继节点纵坐标来完成,而广度优先恰恰意味着后继节点非常少,在绝大多数情况下,好运常在,O(E) 时间复杂度即可完成。

要点就是广度优先遍历。

我先解释广度优先和深度优先两种遍历方式的不同:
在这里插入图片描述

来看 dijkstra 算法本身,将节点不断加入 closeset 的过程就是广度优先遍历的过程,如果节点不是离散的,而是连续的,这意味着边缩短到无穷小而不再有权重,那么广度优先遍历能确保首先接触到的节点一定是距离最短的节点。广度优先遍历会系统地检查从起点出发的每一步距离,确保它找到的第一个目的地的路径一定是最短的。这是因为它按波次向外扩展,首先检查所有与起始点直接相邻的点,然后检查与这些点相邻的点,以此类推。

通常经理们喜欢讲 “爆炸半径” 这个词,爆炸半径越小,波及面越小,但也是最先被波及到。控制爆炸半径就是尽量让爆炸只影响它直接接触到的第一波接触面,因为爆炸本身就是广度优先遍历,一圈一圈向外,只不过它是并行的。

为了理解距离短一定先接触,可以手工做一张图,节点用绳子打的结模拟,边就是绳子,边的权值就是绳子长度,往外抻这张网直到绳子变紧拉不动了停止,那些拉紧的绳子就是最短路径,在源点放一些蚂蚁,看看蚂蚁先到达哪里。

但对于算法,我们必须理解算法的本质,由于人脑和计算机的秉性,算法是一个流程,一个串行的步骤序列,所以算法无法 “一下子看出谁距离 S 最近”,算法必须通过一系列步骤去比对,而广度优先遍历就是最有效的方式,它非常形象地模拟了 “一圈一圈向外按波次扩展” 的过程。

如果你到了一个陌生的城市,找最近的路,比如找回家最短的路,去商场最短的路,去公园最短的路,不依赖现代导航,纯粹 citywalk 步行找路,是深度优先,一条路见路口就拐,还是广度优先,不同的路都试一下呢?

在实际中,可以将广度优先搜索策略简化为 “始终选择离你最近的未探索路径”,这就是 dijkstra 算法的核心。当你来到一个十字路口,你总是先探索离你最近的未走过的街道,而不是随机选择或深入一条特定的路径。

相比之下,深度优先搜索可能会导致你走过一些不必要的长路,甚至可能会多次经过相同的地方,除非你有很好的记忆或者有某种方式来标记已经探索过的路径。深度优先策略更适合探索迷宫或查找任何可达但不一定最短的路径。

有人认为人脑并不擅长即时地计算和记忆复杂的路径图,所以必须要有个导航,但导航背后大概率还是 dijkstra 算法,使用现代导航工具或询问当地居民通常更实用,但对我而言,幸运的是,我个人非常擅长 citywalk 并寻找计算最短路径,从 4,5 岁直到现在,我一直保持着 citywalk 的习惯,第一次是 4 岁半从安阳市钟楼经过北大街走到北门,绕行解放路走到铁狮口迷路,硬摸回家,最后一次就是今天,嘉定环城河跑步一圈后从东大街走到温宿路拐入博乐路进入州桥,经清河路走到罗宾森,吃了一顿本清素酸菜鱼。

这也许就是我擅长图论图算法的原因吧,实践经历加上一点天赋历练出来的,虽然我不懂那些技术术语,但我能给人直感,直击本质。

浙江温州皮鞋湿,下雨进水不会胖。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值