《算法图解》系列笔记(七)—— 狄克斯特拉算法

狄克斯特拉算法(Dijkstra’s algorithm)

广度优先搜索来查找两点之间的最短路径,那时“最短路径”的意思是段数最少。在狄克斯特拉算法中,你给每段都分配了一个数字或权重,因此狄克斯特拉算法找出的是总权重最小的路径。
dijkstra

术语

该算法用于每条边都有关联数字的图,这些数字称为权重(weight
带权重的图为加权图(weighted graph),不带权重的图为非加权图(unweighted graph)

计算非加权图中的最短路径,可使用广度优先搜索。计算加权图中的最短路径,可使用狄克斯特拉算法。
可能有环的存在:绕环的路径不可能是最短的路径,在无向图中,每条边都是一个环。狄克斯特拉算法只适合于有向无环图(directed acyclic graph,DAG)

负权边

不能将狄克斯特拉算法用于包含负权边的图。在包含负权边的图中,要找出最短路径,可使用另一种算法——贝尔曼-福德算法(Bellman-Fordalgorithm)

实现

代码如下:(书中有详细的每一步过程描述)

graph = {}            #整个图的散列表
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["fin"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["fin"] = 5
graph["fin"] = {}

infinity = float("inf")      #散列表是开销
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["fin"] = infinity

parents = {}            #散列表是父子节点
parents["a"] = "start"
parents["b"] = "start"
parents["fin"] = None

processed = []

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 node not in processed:
            lowest_cost = cost
            lowest_cost_node = node
    return lowest_cost_node

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)    #找出接下来要处理的节点,并循环
print(costs)
print(parents)
小结
1. 广度优先搜索用于在非加权图中查找最短路径。
2. 狄克斯特拉算法用于在加权图中查找最短路径。
3. 仅当权重为正时狄克斯特拉算法才管用。
4. 如果图中包含负权边,请使用贝尔曼-福德算法。
加深理解的例子

这里写图片描述
这里写图片描述

就上面的例子来说,是根据A到图中其余点的最短路径长度进行排序,路径越短越先被找到,路径越长越靠后才能被找到,要找A到F的最短路径,我们依次找到了
A –> C 的最短路径 3
A –> C –> B 的最短路径 5
A –> C –> D 的最短路径 6
A –> C –> E 的最短路径 7
A –> C –> D –> F 的最短路径 9
Dijkstra 算法运行的附加效果是得到了另一个信息,A到C的路径最短,其次是A到B, A到D, A到E, A到F

为什么Dijkstra 算法不适用于带负权的图?
就上个例子来说,当把一个点选入集合S时,就意味着已经找到了从A到这个点的最短路径,比如第二步,把C点选入集合S,这时已经找到A到C的最短路径了,但是如果图中存在负权边,就不能再这样说了。举个例子,假设有一个点Z,Z只与A和C有连接,从A到Z的权为50,从Z到C的权为-49,现在A到C的最短路径显然是A –> Z –> C

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值