zoukankan      html  css  js  c++  java
  • 《图解算法》读书笔记(七) 狄克斯特拉算法

    章节内容

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

    前言

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

    使用狄克斯特拉算法

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

    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算法
  • 相关阅读:
    Shell脚本学习笔记2
    Shell脚本学习笔记1
    华大MCU硬件SMBus的应用
    华大MCU的应用中的问题记录
    STM32定时器输入捕获功能应用——超声波模块
    STM32定时器应用——PWM
    利用KEIL的软件仿真的逻辑分析仪功能观察GPIO的波形
    周期性过程数据通信和非周期性邮箱数据通信
    JDBCUtils
    反射
  • 原文地址:https://www.cnblogs.com/prelude1214/p/13611342.html
Copyright © 2011-2022 走看看