Dijkstra算法略讲及代码实现

一、简述

一种应用贪心策略的单源最短路径算法, 计算源点到所有结点的最短路径,主要解决带权重的图结构。

二、核心思想

  1. 初始: 确认源点的最短路径估值为0,其余的顶点的最短路径估值均为无穷大
    (由于源点到源点,显然是最自然最短路径,而源点到其他顶点的距离尚不知道,故假设为无穷大,或者说是无法达到)
  2. 迭代: 每次从所有点中锁定最短路径估值最小的顶点(前面已被锁定的顶点不再参与排序),对该顶点进行松弛操作
  3. 终止: 不断进行步骤2直到所有顶点都被锁定。

最短路径估值: 源点 s s s u u u的最短路径估计值
u u u: 是除了源点 s s s外的顶点


松弛操作

s s s u u u的最短路径已经确定,则调整 u u u的邻接点 v v v( v ∈ u . A d j ) v \in u.Adj) vu.Adj)的最短路径估值。

  • 如果存在源点 s s s v v v的最短路径估值大于源点 s s s u u u再到 v v v的最短路径估值,则将 v v v点的前驱设为 u u u,并将 v v v的最短路径估值更新为源点 s s s u u u再到 v v v的最短路径估值

u u u: 是除了源点 s s s外的顶点
v v v: u u u的邻接点
u . A d j u.Adj u.Adj u u u的邻接顶点集合

作用: 通过松弛操作确保最短路径的边界 v v v的最短路径估值尽可能小。因为我们已经确认源点到 v v v前驱的最短路径,那么 s s s v v v的最短路径,要么本身已经被确认(即源点无法达到 v v v或者 v v v就是源点)为最短路径,要么是基于其前驱的路径上的。当然,为了上面的说法能成立,该算法仅能用于边的权值不可为负权的图

三、代码实现

import math

# 节点个数
vex_num  = 6
# 邻接矩阵,用于存储边的权值
matrix   = [[float('inf')] * vex_num for i in range(vex_num)]
# 记录已被确认最短距离的点
is_fixed = [False] * vex_num
# 记录可达点最短距离
dis      = [float('inf')] * vex_num

# init matrix(一个用例测试)
matrix[0][2] = 10
matrix[0][4] = 30
matrix[0][5] = 100

matrix[1][2] = 5

matrix[2][3] = 50
matrix[3][5] = 10

matrix[4][5] = 60
matrix[4][3] = 20

# 设置起点
start_vex = 0

# init dis
for i in range(vex_num):
    dis[i] = matrix[start_vex][i]
    
# init fix list
is_fixed[start_vex] = True

# 第i个元素表示,第i个节点的前驱节点标号
path = [None] * vex_num

# init path
for i in range(vex_num):
    if not math.isinf(matrix[start_vex][i]):
        path[i] = start_vex

# 获取尚未被确定的最短距离的点
def get_min_dis():
    vex = None
    min = float('inf')
    for i in range(vex_num):
        if is_fixed[i] == False and dis[i] < min:
            min = dis[i]
            vex = i

    return vex


def algo():        
    while True:
        vex = get_min_dis()
        # 所有点都已经固定
        if(vex is None):
            break
        
        is_fixed[vex] = True

        # 对vex进行松弛
        for i in range(vex_num):
            # 获取vex邻接节点
            power = matrix[vex][i]
            if math.isinf(power):
                continue

            adjvex = i
            if dis[adjvex] > dis[vex] + power:
                dis[adjvex] = dis[vex] + power
                path[adjvex] = vex


    
    
algo()

# 打印可达路径
for i in range(vex_num):
    msg = []

    j = i
    while path[j] is not None:
        j = path[j]
        msg.append(j) 

    msg.reverse()
    msg.append(i) 
    print(i, msg)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值