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)
本文来自博客园,作者:Kenny_LZK,转载请注明原文链接:https://www.cnblogs.com/liuzhongkun/p/16530421.html