图论:最短路径——Dijkstra(迪杰斯特拉)算法

求一个节点到其他所有节点的最短路径

思路——贪心算法:

  1. 假设源点为 u,将所有节点分为 S 和 V 两个集合,集合 S 中保存已经确定最短路径的节点,集合V中保存未确定最短路径的节点,源点 u 可以借助集合 S 中的节点作为中间节点到达集合 V 中的节点;定义一个数组 dist 记录源点 u 到其他节点的最短路径,一个数组 pre 记录每个节点最短路径的前驱节点。
  2. 初始时,集合 S 中只有源点 u,集合 V 中有其他所有节点;将 dist 数组初始化为源点 u 直接到其他节点的路径,pre 数组中所有节点的前驱初始化为源点 u。
  3. 每次选择当前路径最短的节点 v 加入到集合 S 中,然后更新 dist 数组和 pre 数组。假设当前路径最短的节点 v 的最短路径是 t,更新 dist 数组的公式是 min(dist, dist + t),然后将 dist 数组中路径值发生变化的节点的 pre 更新为 v。
  4. 直到所有节点都在集合 S 中,源点到其他所有节点的最短路径计算结束。
  5. 想要知道源点到一个节点 v 的最短路径上的节点,可以通过查询 pre 数组。
    5.1 首先通过 pre 数组查询节点 v 的前驱节点,将该前驱节点加入栈中。
    5.2 然后查询该前驱节点的前驱节点加入栈中。
    5.3 重复查询前驱节点,直到找到源点 u,加入栈。
    5.4 最后栈顶到栈底就是源点 u 到节点 v 的最短路径上的节点。

python代码:

import math


def dijkstra(node, graph):
    node_num = len(graph)
    # 初始化 dist 和 pre 数组
    # 包含node本身的,因为node不一定是第一个节点,所有包含会方便很多
    dist = []
    pre = [-1] * node_num
    for i in range(node_num):
        dist.append(graph[node][i])
        if graph[node][i] != math.inf:
            pre[i] = node

    # 初始一个数组记录节点是否加入 S
    flag = [False] * node_num
    flag[node] = True

    # 更新最短路径
    while not all(flag):
        # 本次路径最小的节点加入集合 S
        min_dist = math.inf
        min_dist_node = None
        for i in range(node_num):
            if dist[i] <= min_dist and not flag[i]:
                min_dist = dist[i]
                min_dist_node = i

        flag[min_dist_node] = True

        # 更新数组 dist 和 pre
        for i in range(node_num):
            if flag[i]:
                continue

            temp, dist[i] = dist[i], min(dist[i], dist[min_dist_node] + graph[min_dist_node][i])
            if temp != dist[i]:
                pre[i] = min_dist_node

    return dist, pre


if __name__ == '__main__':
    graph = [[0, 3, 4],
             [3, 0, math.inf],
             [4, math.inf, 0]]
    u = 1
    dist, pre = dijkstra(u, graph)
    pass
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值