python算法之Dijkstra算法(迪杰斯特拉)——最短路径问题

python算法之Dijkstra

Dijkstra算法是由荷兰计算机科学家迪杰斯特拉(Dijkstra)于1959 年提出的,因此又叫迪杰斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。

实现原理:
每次新扩展一个距离最短的点,更新与其相邻的点的距离。当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性。不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破坏了已经更新的点距离不会改变的性质。

算法思路:
Dijkstra最短路经算法是一种单源最短路径,针对的是非负权边。所谓单源最短路径就是指定一个出发顶点,计算从该源顶点出发到其他所有顶点的最短路径。
按路径长度递增次序产生算法:
把顶点集合V分成两组:
(1)S:已求出的顶点的集合(初始时只含有源点V0)
(2)V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,
保证:
(1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
(2)每个顶点对应一个距离值
S中顶点:从V0到此顶点的长度
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度

依据:可以证明V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和

代码实现:

import networkx as nx


def Dijkstra(G, start, end):
    RG = G.reverse();
    dist = {};
    previous = {}
    for v in RG.nodes():
        #都设置为无穷大
        dist[v] = float('inf')
        previous[v] = 'none'
    dist[end] = 0
    u = end
    print(dist)
    print(min(dist, key=dist.get))
    while u != start:
        #获得最小值对应的键
        u = min(dist, key=dist.get)
        distu = dist[u]
        # print(distu)
        del dist[u]
        print(RG.edges(u))
        print(RG[u])
        for u, v in RG.edges(u):
            if v in dist:
                alt = distu + RG[u][v]['weight']
                if alt < dist[v]:
                    dist[v] = alt
                    previous[v] = u
    path = (start,)
    last = start
    while last != end:
        nxt = previous[last]
        path += (nxt,)
        last = nxt
    return path

#实例化一个空的图
G = nx.DiGraph()
#添加边
G.add_edge(0, 1, weight=80)
G.add_edge(1, 2, weight=50)
G.add_edge(1, 3, weight=30)
G.add_edge(3, 2, weight=10)
G.add_edge(2, 4, weight=20)
G.add_edge(2, 5, weight=30)
G.add_edge(4, 5, weight=10)
G.add_edge(5, 3, weight=5)
G.add_edge(2, 6, weight=10)
G.add_edge(4, 6, weight=10)
G.add_edge(3, 6, weight=25)
G.add_edge(5, 6, weight=35)

rs = Dijkstra(G, 0, 6)
print(rs)

运行结果:
(0, 1, 3, 2, 6)

猜你喜欢

转载自blog.csdn.net/huang_yong_peng/article/details/81916554