Python实现dijkstra算法

dijkstra算法

一、 简介

1、 概念

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

二、 实现原理

1、 动图演示

2、 思路解析

S集合 U集合
选A为起点,S={A}
此时的最短路径
A->A=0
以A为中心点,从A开始查找
U={B, C, D, E, F}
A->B=10
A->D=4
A->{E, F, C}=\(\infty\)
d(AD)最短
选入D,此时S={A, D}
此时最短路径
A->A=0
A->D=4
以D为中间点,从A->D这条最短路径进行查找
U={B, C, E, F}
A->D->B=6 < 10
A->D->E=10
A->D->C=19
A->D->F=\(\infty\)
d(ADB)最短
选入B,此时S={A, D, B}
此时最短路径
A->A=0
A->D=4
A->D->B=6
以B为中间点,从A->D->B这条路径进行查找
U={C, E, F}
A->D->B->C=14<19
A->D->B->E=12>10
A->D->B->F=\(\infty\)
d(ADE)最短
选入E,此时S={A, D, B, E}
此时最短路径
A->A=0
A->D=4
A->D->B=6
A->D->E=10
以E为中间点,从A->D->E这条路径进行查找
U={C, F}
A->D->E->C=11<14
A->D->E->F=22
d(ADEC)最短
选入C,此时S={A, D, B, E, C}
此时最短路径
A->A=0
A->D=4
A->D->B=6
A->D->E=10
A->D->E->C=11
以C为中间点,从A->D->E->C这条路径进行查找
U={F}
A->D->E->C->F=16
发现最短路径为A->D->E->C->F
选入F,此时S={A, D, B, E, C, F}
此时最短路径
A->A=0
A->D=4
A->D->B=6
A->D->E=10
A->D->E->C=11
A->D->E->C->F=16
以F为中间点,从A->D->E->C->F这条路径进行查找
集合为空,查找完毕

最后,我们得出

路径 距离
A->A 0
A->D 4
A->D->B 6
A->D->E 10
A->D->E->C 11
A->D->E->C->F 16

三、 代码实现

1、 构建矩阵

我们使得与节点有直接接触的节点的距离为确定值,没有直接接触的节点为无穷大,然后构建一个二维矩阵

A B C D E F
A 0 10 \(\infty\) 4 \(\infty\) \(\infty\)
B 10 0 8 2 6 \(\infty\)
C \(\infty\) 8 0 15 1 5
D 4 2 15 0 6 \(\infty\)
E \(\infty\) 6 1 6 0 12
F \(\infty\) \(\infty\) 5 \(\infty\) 12 0

2、 算法实现

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo02.py"
__email__ = "liu.zhong.kun@foxmail.com"
MAX = float('inf')

def dijkstra(matrix, start_node):
    matrix_length = len(matrix)  # 矩阵一维数组的长度,即节点的个数

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

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

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

    # 将访问节点中未访问的个数作为循环值,其实也可以用个点长度代替。
    while used_node.count(False):
        min_value = MAX
        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,10,MAX,4,MAX,MAX],
    [10,0,8,2,6,MAX],
    [MAX,8,10,15,1,5],
    [4,2,15,0,6,MAX],
    [MAX,6,1,6,0,12],
    [MAX,MAX,5,MAX,12,0]
]
ret = dijkstra(matrix_, 0)
print(ret)
posted @ 2022-07-28 22:00  Kenny_LZK  阅读(2788)  评论(0编辑  收藏  举报