• 《图解算法》读书笔记(七) 狄克斯特拉算法


    章节内容

    • 加权图
    • 狄克斯特拉算法
    • 图中的环,导致狄克斯特拉算法不管用

    前言

    在之前一个章节中,我们学会了使用广度优先搜索去查找最短路径。但其实在现实问题中,每个路径的长度都是不同的。
    所以我们只是找到了一个最少连线的路径。在这一章节,我们将学会使用狄克斯特拉算法去查找加权图的最短路径。

    使用狄克斯特拉算法

    狄克斯特拉算法包含四个步骤:

    1. 找出加权最少的邻居
    2. 更新该节点的邻居的路径
    3. 重复第二个步骤,直到图中的每个节点都这样做了
    4. 计算最终路径

    术语

    权重:每条边上的关联数字
    加权图:带权重的图
    非加权图:不带权重的图
    狄克斯特拉算法只适用于有向无环加权图

    负权边

    如果边的权有为负数的,也不适合用狄克斯特拉算法算法;
    可使用另一种算法:贝尔曼-福德算法(Bellman-Ford)。
    为什么不适合用狄克斯特拉算法?
    狄克斯特拉算法是基于之前的节点的最短路径计算之后的节点,如果有负权边,则可能影响之前节点的最短路径,那样所有这个节点后的节点计算都存在问题。

    实现

    首先我们需要一个散列表存储图的数据,和上一章节不同,我们需要存储邻居的节点,以及到这些节点的开销,所以我们采用二维散列表。
    比如:

    graph = {}
    graph["start"] = {}
    graph["start"]["a"] = 6
    graph["start"]["b"] = 2
    

    然后我们需要另一个散列表来存储从起点到每个节点的开销。对于还不知道开销的节点的值可以设置为无限大,python中可以表示为:
    infinity = float("inf")
    创建开销表的代码如下:

    infinity = float("inf")
    costs = {}
    costs["a"] = 6
    costs["b"] = 2
    costs["fin"] = infinity
    

    还需要一个存储父节点的散列表
    创建这个散列表的代码如下:

    parents = {}
    parents["a"] = "start"
    parents["b"] = "start"
    parents["fin"] = None
    

    最后需要一个散列表存储处理过的节点。
    准备工作做好了,下面来看看算法步骤:

    1. 只要还有要处理的节点
    2. 获取离起点最近的节点
    3. 更新其邻居的开销
    4. 如果有邻居的开销被更新了,同时更新其父节点
    5. 将该节点标记为处理过
      重复以上五个步骤直至所有节点都已处理,代码如下:
    node = find_lowest_cost_node(costs)
    while node is not None:
          cost = costs[node]
          neighbors = graph[node]
          for n in neighbors.keys():
                new_cost = cost + neighbors[n]
                if costs[n] > new_cost:
                      costs[n] = new_cost
                      parents[n] = node
          processed.append(node)
          node = find_lowest_cost_node(costs)
    
    def find_lowest_cost_node(costs):
          lowest_cost = float("inf")
          lowest_cost_node = None
          for node in costs:
                cost = costs[node]
                if cost < lowest_cost and not not in processed:
                      lowest_cost = cost
                      lowest_cost_node = node
          return lowest_cost_node
    

    小结

    1. 广度优先搜索用于在非加权图中查找最短路径
    2. 狄克斯特拉算法用于在加权图中查找最短路径
    3. 仅当权重为正时狄克斯特拉算法管用
    4. 如果图中包含负权边,请使用Bellman-Ford算法
  • 相关阅读:
    世界视频编码器大赛结果揭晓,腾讯V265编码器勇夺两项第一
    IDEA实用教程(六)—— 全局设置的两种方式
    IDEA实用教程(五)——配置IDEA的JVM内存值
    IDEA实用教程(四)—— 创建JavaSE工程
    IDEA实用教程(三)
    IDEA实用教程(二)
    emlog博客的安装教程
    IDEA实用教程(一)
    阿里云轻量应用服务器快照的使用及注意事项
    mysql5.5安装教程
  • 原文地址:https://www.cnblogs.com/prelude1214/p/13611342.html
Copyright © 2020-2023  润新知