2018.7.19 学习日志-----Dijkstra算法找出有权图的单源最短路(Python)

Dijkstra算法(狄克斯特拉算法)来解决有权的单源最短路

前面我学习了广度优先搜索算法来解决无权图的单源最短路的问题
而要解决有权图的单源最短路的问题可以使用Dijkstra算法
我利用python语言来解决这个问题

Dijkstra算法
1.算法的思想:
通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是”起点s到该顶点的路径”。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 … 重复该操作,直到遍历完所有顶点

2.操作步骤
1.创建三个散列表(graph,dist,PATH)
第一个graph实现图的结构
第二个dist代表了起点到每个点最短路径的长度
第三个PATH用来存储节点的父节点
2.找出路径最短的节点,遍历其相邻的节点,检查是否有前往它们的更短的路径,若有就更新信息
3.重复这过程,直到对图中所有的节点都进行了这样子的操作
4.计算最终路径

3.实例+代码
例图:
《2018.7.19 学习日志-----Dijkstra算法找出有权图的单源最短路(Python)》

代码:

# 狄克斯特拉算法:可以用于解决有权图的单源最短路问题
# 第一步找出未处理的节点中dist最小的节点
def find_lowest_dist_node(dist):
    lowest_dist = float('inf')
    lowest_dist_node = None
    for node in dist:  # 遍历所有的节点
        value = dist[node]  # 得到节点对应的值
        if (value < lowest_dist and node not in add):
            lowest_dist = value
            lowest_dist_node = node
    return lowest_dist_node  # 返回了最小的节点


# 接下来处理这个节点
def handle(dist):
    while True:
        node = find_lowest_dist_node(dist)  # 得到未处理的节点中dist最小的节点
        if node is None:  # 如果节点不存在
            break
        for i in graph[node]:  # node节点遍历相邻的节点
            if (dist[node] + graph[node][i] < dist[i]):  # graph[node][i]表示权重值
                dist[i] = dist[node] + graph[node][i]  # 更新dist
                PATH[i] = node  # 更新父节点
        add.append(node)  # 记录下这个节点,表示已经被处理
    print("dist: ", dist)
    print("PATH: ", PATH)


# 构建图
graph = {}
graph['A'] = {}
graph['A']['B'] = 6
graph['A']['C'] = 2
graph['B'] = {}
graph['B']['D'] = 1
graph['C'] = {}
graph['C']['D'] = 5
graph['C']['B'] = 3
graph['D'] = []  # 表示后面没有其他节点
# 构建dist{},dist[]代表了起点到每个点最短路径的长度
dist = {}
dist['A'] = 0  # 把A作为起点,起点到起点的距离为0
x = float('inf')  # float('inf')表示正无穷,其他顶点dist设置为无穷大
dist['B'] = 6  # 与起点的相邻的两个节点的dist初始化为权重
dist['C'] = 2
dist['D'] = x
# 构建PATH{},PATH用来存储节点的父节点
PATH = {}
PATH['A'] = -1
PATH['B'] = 'A'  # 将与起点相邻的节点直接初始化为A
PATH['C'] = 'A'
PATH['D'] = -1
add = []  # 记录被处理过的节点
add.append('A')  # 应为已经将A相邻的两个节点初始化过了,所以A就不用在进行检查了

print("原dist:{}".format(dist))
print('原PATH:{}'.format(PATH))
handle(dist)


#输出
原dist:{'A': 0, 'B': 6, 'C': 2, 'D': inf}
原PATH:{'A': -1, 'B': 'A', 'C': 'A', 'D': -1}
dist:  {'A': 0, 'B': 5, 'C': 2, 'D': 6}
PATH:  {'A': -1, 'B': 'C', 'C': 'A', 'D': 'B'}

对于输出的解释:
dist: {‘A’: 0, ‘B’: 5, ‘C’: 2, ‘D’: 6}
到达B,C,D的最小距离分别是5,2,6
PATH: {‘A’: -1, ‘B’: ‘C’, ‘C’: ‘A’, ‘D’: ‘B’}
假设目标点是D:D父节点是B,B的父节点是C,C的父节点是A,
所以到D的最短路径怎么走:A->C->B->D

问题:
float(“inf”) Python中能够表示无穷大
dist[“D”]的值为什么不能想广度优先搜索里面初始化为-1,负无穷
因为在这条语句中dist[node] + graph[node][i] < dist[i]一点不成立所以不行

以后不明白了还是看看陈越老师的数据结构视频

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/Yk_0311/article/details/81108963
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞