使用python实现Dijkstra算法

前言:

楼主接触编程仅仅4个月,凑巧学校做python大作业,来分享一下编程思路,供大家讨论交流

(楼主第一次做出来算法,将实现想法和具体代码呈现在下文,供大家评鉴,希望楼主和大家的编程水平共同进步!)

关于Dijkstra算法

   

荷兰数学家 E.W.Dijkstra 于 1959 年提出了 Dijkstra 算法,它是一种适用于 非负权值 网络的 单源最短路径算法,同时也是目前求解最短路径问题的理论上最完备、应用最广的经典算法。它可以给出从指定节点到图中其他节点的最短路径,以及任意两点的最短路径。

Dijkstra 算法是一种基于 贪心策略 的最短路径算法,该种算法的原理是按照路径长度逐点增长的方法构造一棵路径树,从而得出从该树的根节点(即指定节点)到其他所有节点的最短路径。

本质上这是一个图论问题,要求一个起始点到各点的最短路径,相较于深度优先搜索和广度优先搜索算法来讲,Dijkstra算法的优点在于它可以处理有向图问题,前者只能处理无向图问题,何为有向图呢,即是从A到B和从B到A的结果并不相等,类似与上山和下山的情况。

举例

这里用无向图来举个例子,因为无向图要简单一些。

如图,要求从A到各点的最短距离,我们可以先做两个列表,来划分已算出最短路径的情况和待定的情况。可以划分为S和U

下面进行实践:

A的最短距离即是A,distance(A,A)=0

图中可以看出A与B和D紧邻,有distance(A,B)=10,distance(A,D)=4,

比较发现AD更短,而且在全图中也不可能有AD更短的路径出现,因为是紧邻的情况,如果有通过中间量来更短的话,那必然会有A-B-X的路径,而A-B没有A-D大,所以上述假设不成立。

接下来从D出发,沿着B,C,E三条路线依次迭代即可,横向,纵向对比即可

根据上述解释后,进行迭代即可

S:A-A=0       U:A-B=10;A-D=4

S:A-A=0 A-D=4  U:A-D-B=6<10;A-D-C=19;A-D-E=10;

S:A-A=0 A-D=4 A-D-B=6  U:A-D-B-C=14;A-D-B-E=12>10

S:A-A=0,A-D=4,A-D-B=6,A-D-E=10, U:A-D-B-E-C=13<14;A-D-B-E-F=24

S:A-A=0,A-D=4,A-D-B=6,A-D-B-E=12,A-D-B-E-C=13,U:A-D--E-C-F=16

S:A-A=0,A-D-B=6,A-D-E-C=11,A-D=4,A-D-E=10 ,A-D-E-C-F=16,U为空集

迭代结束

  现在用python语言具体实现一下

代码实现

Python编程要求:

  1. 第一步输入全图有多少个点;
  2. 第二部:逐次输入Vij的长度,Vii=0,Vij没有直接关联的边的时候则输入“inf”,代替上图中的“∞”;
  3. 第三步输入要计算Dijkstra算法的起始点,然后输出这个起始点到其他节点的最短路径

#dijkstra算法需要分为三步,分别为输入节点与权重,计算比较路径,输出结果
#输入节点与权重
R=['V1','V2','V3','V4','V5','V6']
V1=[0,9,1,  3,'inf','inf']
V2=[1,0,  4,'inf',7,  'inf']
V3=[  2,  'inf',0,'inf',7,  'inf']
V4=['inf','inf',5,  0,  2,    7]
V5=['inf',  6,  2,  8,  0,    5]
V6=[  7,  'inf',2,'inf',2,    0]  # 这个为有向图做法
INF = float('inf')
print('现在输入6个点,分别为V1,V2,V3,V4,V5,V6,权重在下图中展现')
print(R)
print(f'V1:{V1}\t')
print(f'V2:{V2}\t')
print(f'V3:{V3}\t')
print(f'V4:{V4}\t')
print(f'V5:{V5}\t')
print(f'V6:{V6}\t')
#计算比较最优路径
def dijkstra(matrix, start_node):
    matrix_length = len(matrix)  # 矩阵一维数组的长度,即节点的个数

    used_node = [False] * matrix_length  # 访问过的节点数组

    distance = [INF] * matrix_length  # 最短路径距离数组

    distance[start_node] = 0  # 初始化,将起始节点的最短路径修改成0

    # 将访问节点中未访问的个数作为循环值,其实也可以用个点长度代替。
    while used_node.count(False):
        min_value = INF
        min_value_index = -1

        # 在最短路径节点中找到最小值,已经访问过的不在参与循环。
        # 得到最小值下标,每循环一次肯定有一个最小值
        for index in range(matrix_length):
            if not used_node[index] and distance[index] < min_value:
                min_value = distance[index]
                min_value_index = index

        # 将访问节点数组对应的值修改成True,标志其已经访问过了
        used_node[min_value_index] = True

        # 更新distance数组。
        # 以B点为例:distance[x] 起始点达到B点的距离。
        # distance[min_value_index] + matrix[min_value_index][index] 是起始点经过某点达到B点的距离,比较两个值,取较小的那个。
        for index in range(matrix_length):
            distance[index] = min(distance[index], distance[min_value_index] + matrix[min_value_index][index])

    return distance
#输出并计算结果
matrix_ = [
    [0, 9, 1, 3, INF, INF],
    [1, 0, 4, INF, 7, INF],
    [2, INF, 0, INF, 1, INF],
    [INF, INF, 5, 0, 2, 7],
    [INF, 6, 5, 8, 0, 5],
    [7, INF, 2, INF, 2, 0]
]
ret = dijkstra(matrix_, 0)

#将Matrix函数计算出来的结果存入空列表M中,
M=list()
for i in ret:
    M.append(i)
#输出最终结果
print(f'现在展示起始点V1到各点的最短距离')
print(f'V1到V1的最短距离为{M[0]}')
print(f'V1到V2的最短距离为{M[1]}')
print(f'V1到V3的最短距离为{M[2]}')
print(f'V1到V4的最短距离为{M[3]}')
print(f'V1到V5的最短距离为{M[4]}')
print(f'V1到V6的最短距离为{M[5]}')

具体输出结果

 

  后记

这个代码美中不足的就是他其实并没有展现出最短路径到底是啥,只是输出了最短路径是多大,所以这个代码还可以在此处优化,而且后续其他算法问题也有不少是根据Dijkstra算法优化的,那些是更实用的,还需要继续学习才是,新人第一次写如此庞大的项目,明显看出编程功底很不熟练,还需继续多多做题才是,后续将继续在CSDN上写python,java,C(C++)的问题,感谢各位一同交流,讨论代码。

  • 44
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值