最短路径Dijkstra讲解,工具包使用 python

Dijkstra讲解

原理
Dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。初始时,集合T只有顶点s
然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,此时完成一个顶点, 然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。 然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。

利用动态规划来求解。
算法伪代码

    清除所有点的标号;
    设d[0]=0,其他d[i]=INF;//INF是一个很大的值,用来替代正无穷
    循环n次 { 
        在所有未标号结点中,选出d值最小的结点x;
        给结点x标记;
        对于从x出发的所有边(x,y),更新d[y] = min{d[y], d[x]+w(x,y)} 

在这里插入图片描述
根据图来讲解。假设我们要求图中1到5 的最短路径。
1.首先我们得到一个邻接矩阵或者其他存储我们的边和点关系。

#自定义网络
row=np.array([1,1,1,2,2,3,3,6,5])
col=np.array([2,3,6,3,4,6,4,5,4])
value=np.array([7,9,14,10,15,2,11,9,6])

row和col 分别表示一条边的两个顶点。value表示长度。
假设我们要计算顶点1到顶点5放入最短路径。
首先我们得有一个数组保存我们访问过的点。
和一个矩阵保存着点到每个点的距离。矩阵大小为n*n,与源点不相邻的边初始值为inf 无穷大。n表示顶点个数。命名为距离矩阵
(1)从源点1出发,把源点1保存到已访问的点数组中。发现源点1可以到达的点有顶点2,3,6修改距离矩阵中源点1到顶点2,3,6的距离。
(2)发现源点1到顶点2 的距离最小,我们走到2。把顶点2保存到已访问的点中。
(3)到达顶点2,发现顶点2可以到达的未访问过的点有顶点3和顶点4(顶点1为访问过已保存到数组中),修改距离矩阵中顶点2到顶点3和顶点4的距离。。如果存在(顶点1到顶点2的距离加上顶点2到顶点3的距离)小于(顶点1到顶点3的距离),则修改距离矩阵源点1到顶点3的距离。同时修改顶点2到顶点4的距离。
(4)到达顶点3,发现顶点3可以到达的点有源点1,顶点6,顶点4。修改顶点3到顶点6和顶点4的距离为2,11。并且发现(源点1到顶点3的距离加顶点3到顶点6的距离) 小于( 源点1到顶点3的距离)。则修改距离矩阵中源点1到顶点3的距离为9+2=11。
(5)顶点3出发,选择最近的点,到达顶点6。顶点5可以到达的点为源点1和顶点6,修改顶点5到顶点6的距离。同时修改顶点1到顶点5的距离为9+2+9
所有顶点1到顶点5最短路径 顶点1-顶点3-顶点6-顶点5.

公式

源点到顶点j的距离=min(源点到顶点j的距离(开先定义的距离数据库中距离),源点到顶点j相邻点i的距离+顶点i与顶点j的距离)

networkx 使用求解

无向图
nx.Graph() 无向图

import networkx as nx
import pylab
import numpy as np
import matplotlib; matplotlib.use('TkAgg')
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
#自定义网络

row=np.array([0,0,0,1,1,2,2,5,4])
col=np.array([1,2,5,2,3,5,3,4,3])
value=np.array([7,9,14,10,15,2,11,9,6])

print('生成一个空的有向图')
G=nx.Graph()
print('为这个网络添加节点...')
for i in range(0,np.size(col)+1):
    G.add_node(i)
print('在网络中添加带权中的边...')
for i in range(np.size(row)):
    G.add_weighted_edges_from([(row[i],col[i],value[i])])

print('给网路设置布局...')
pos=nx.shell_layout(G)
print('画出网络图像:')
nx.draw(G,pos,with_labels=True, node_color='white', edge_color='red', node_size=400, alpha=0.5 )
pylab.title('路径图',fontsize=15)
pylab.show()

print('dijkstra方法寻找最短路径:')
path=nx.dijkstra_path(G,source=0, target=4)
print('节点0到4的路径:真实1到5', path)
print('dijkstra方法寻找最短距离:')
distance=nx.dijkstra_path_length(G, source=0, target=4)
print('节点0到4的距离为:', distance)
row=np.array([0,0,0,1,1,2,2,5,4])
col=np.array([1,2,5,2,3,5,3,4,3])
value=np.array([7,9,14,10,15,2,11,9,6])

row 和col 对应边的两个顶点 :0对应原始图中的1,1对应原始图中的2,value为长度。
路径图
在这里插入图片描述
结果:
在这里插入图片描述
路径对应原始图中为1,3,6,5。

有向图
G=nx.DiGraph()# 为有向图

import networkx as nx
import pylab
import numpy as np
import matplotlib; matplotlib.use('TkAgg')
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
#自定义网络

row=np.array([0,0,0,1,1,2,2,5,4])
col=np.array([1,2,5,2,3,5,3,4,3])
value=np.array([7,9,14,10,15,2,11,9,6])

print('生成一个空的有向图')
G=nx.DiGraph()
print('为这个网络添加节点...')
for i in range(0,np.size(col)+1):
    G.add_node(i)
print('在网络中添加带权中的边...')
for i in range(np.size(row)):
    G.add_weighted_edges_from([(row[i],col[i],value[i])])

print('给网路设置布局...')
pos=nx.shell_layout(G)
print('画出网络图像:')
nx.draw(G,pos,with_labels=True, node_color='white', edge_color='red', node_size=400, alpha=0.5 )
pylab.title('路径图',fontsize=15)
pylab.show()



print('dijkstra方法寻找最短路径:')

path=nx.dijkstra_path(G,source=4, target=5)
print('节点4到5的路径', path)
print('dijkstra方法寻找最短距离:')
distance=nx.dijkstra_path_length(G, source=4, target=5)
print('节点4到5的距离为:', distance)

在这里插入图片描述
求4到5的距离:
运行显示报错。没有路径可达

猜你喜欢

转载自blog.csdn.net/kobeyu652453/article/details/106600778
今日推荐