系列文章目录
第六章:狄克斯特拉算法
前言
积累算法,记录学习
一、加权图
上一章介绍的图是没有权重的,即每一条边的意义一样,这样并不全面,因此引出一种加权图,这种图通常伴随的问题是最快路径问题
比如对应下面这个图,假如使用广度优先算法时,找到的最短路径可能是“起点——A——终点”或者“起点——B——终点”,但是我们可以看出,在图上最快的路径并不是上述两条!因此广度优先搜索算法失效。对于这样的加权图,我们的狄克斯特拉算法就派上了用场。
二、算法原理
我们不用那种索然无味的算法流程,我们还是以上图为例,我们的目的是找到从起点到终点的最快路径,我们分以下步骤进行:
1)找出最近的节点。 我们从起点出发,有两条路能走,前往A点和前往B点,最终目的是终点。并且我们可以知道前往A点用6分钟,前往B点用2分钟,不知道前往终点所需时间,因此设为无穷。所以来说,我们选择B节点这条路,因为它是最快的!拿小本子记下来:
2)计算经B节点前往其各个邻居的所需时间。 现在我们站在B处,能够到达的地方有A和终点,所以从B到A的时间是3分钟,从B到终点的时间是5分钟。由此我们需要更新一下自己的小本子了。因为现在从起点到A点的最快时间是5分钟,到终点的最快时间是7分钟:
3)重复!我们现在再站在A点,由于A点到终点的时间是1分钟,因此又要更新一下小本子,因为现在从起点途径B再途径A再到终点才是我们的最快路径!仅需6分钟,显然这不是我们最短路径。
这些路上的时间在权重图的术语中叫权重
这里需要注意一点,狄克斯特拉算法不能用在包含带有负权重的图中,因为对于处理过的节点,算法认为没有前往该节点的更短路径,这时我们就需要一种新的算法——贝尔曼-福德算法 ,这里暂时先不做详解,感兴趣的小伙伴可以自行学习。
三、算法实现
我们就实现上面这个图的狄克斯特拉算法,使用的数据结构也是散列表:它真是用处多多呢!
1、首先我们需要有存储图的散列表graph,将图上所有的信息表现在散列表中,这就是我们第一步要做的事:
>>> graph = {
}
>>> graph["start"] = {