迪杰斯特拉算法(求最短路径)
迪杰斯特拉算法用于查找图中某个顶点到其它所有顶点的最短路径,该算法既适用于无向加权图,也适用于有向加权图。
注意,使用迪杰斯特拉算法查找最短路径时,必须保证图中所有边的权值为非负数,否则查找过程很容易出错。

图 1 无向加权图
假设用迪杰斯特拉算法查找从顶点 0 到其它顶点的最短路径,具体过程是:
1) 统计从顶点 0 直达其它顶点的权值,如下表所示:

图 2 最短路径 0-1
3) 找到最短路径 0-1 后,沿 0-1 路径方向查找更短的到达其它顶点的路径,并对表 1 进行更新。

图 3 最短路径 0-2
4) 重复之前的操作,沿 0-2 路径方向查找更短的到达其它顶点的路径。遗憾地是,从顶点 2 只能到达顶点 3,且 0-2-3 的总权值比表 2 中记录的 0-1-3 更大,因此表 2 中记录的数据维持不变。
5) 表 3 中,总权值最小的是 0-1-3,它也是顶点 0 到顶点 3 的最短路径。

图 4 最短路径 0-1-3
沿 0-1-3 路径方向,查找到其它顶点更短的路径并更新表 3。更新后的表格为:
6) 表 4 中,总权值最小的是 0-1-3-4,它是顶点 0 到顶点 4 的最短路径。

图 5 最短路径 0-1-3-4
从顶点 4 出发,查找顶点 0 到其它顶点更短的路径并更新表 4。更新后的表格为:
7) 表 5 中,总权值最小的路径是 0-1-3-4-6,它是顶点 0 到顶点 6 的最短路径。

图 6 最短路径 0-1-3-4-6
8) 从图 6 可以看到,只剩下顶点 0 到顶点 5 的最短路径尚未确定。从顶点 6 出发到达顶点 5 的路径是 0-1-3-4-6-5,对应的总权值为 25,大于表 5 中记录的 0-1-3-5 路径,因此 0-1-3-5 是顶点 0 到顶点 5 的最短路径。

图 7 最短路径 0-1-3-5
由此借助迪杰斯特拉算法,我们找出了顶点 0 到其它所有顶点的最短路径,如下表所示:
注意,使用迪杰斯特拉算法查找最短路径时,必须保证图中所有边的权值为非负数,否则查找过程很容易出错。
一、迪杰斯特拉算法的实现思路
图 1 是一个无向加权图,我们就以此图为例,给大家讲解迪杰斯特拉算法的实现思路。
图 1 无向加权图
假设用迪杰斯特拉算法查找从顶点 0 到其它顶点的最短路径,具体过程是:
1) 统计从顶点 0 直达其它顶点的权值,如下表所示:
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
总权值 | 2 | 6 | ∞ | ∞ | ∞ | ∞ |
路径 | 0-1 | 0-2 | 0-3 | 0-4 | 0-5 | 0-6 |
2) 表 1 中,权值最小的是 0-1 路径,它也是从顶点 0 到顶点 1 的最短路径(如图 2 所示)。原因很简单,从顶点 0 出发一共只有 0-1 和 0-2 两条路径,0-2 的权值本就比 0-1 大,所以从 0-2 出发不可能找得到比 0-1 权值更小的路径。∞ 表示两个顶点之间无法直达,对应的权值为无穷大。

图 2 最短路径 0-1
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
总权值 | 2 | 6 | 2+5 | ∞ | ∞ | ∞ |
路径 | 0-1 | 0-2 | 0-1-3 | 0-4 | 0-5 | 0-6 |
更新后的表格如表 2 所示,沿 0-1 路径可以到达顶点 3,且 0-1-3 的总权值比 0-3 更小。表 2 中,总权值最小的路径是 0-2,它也是从顶点 0 到顶点 2 的最短路径,如下图所示。绿色加粗的权值是已确认为最短路径的权值,后续选择总权值最小的路径时不再重复选择;红色加粗的权值为刚刚更新的权值。

图 3 最短路径 0-2
4) 重复之前的操作,沿 0-2 路径方向查找更短的到达其它顶点的路径。遗憾地是,从顶点 2 只能到达顶点 3,且 0-2-3 的总权值比表 2 中记录的 0-1-3 更大,因此表 2 中记录的数据维持不变。
|
1
|
2
|
3
|
4
|
5
|
6
|
---|---|---|---|---|---|---|
总权值
|
2
|
6
|
7
|
∞
|
∞
|
∞
|
路径
|
0-1
|
0-2
|
0-1-3
|
0-4
|
0-5
|
0-6
|

图 4 最短路径 0-1-3
沿 0-1-3 路径方向,查找到其它顶点更短的路径并更新表 3。更新后的表格为:
|
1
|
2
|
3
|
4
|
5
|
6
|
---|---|---|---|---|---|---|
总权值
|
2
|
6
|
7
|
7+10
|
7+15
|
∞
|
路径
|
0-1
|
0-2
|
0-1-3
|
0-1-3-4
|
0-1-3-5
|
0-6
|

图 5 最短路径 0-1-3-4
从顶点 4 出发,查找顶点 0 到其它顶点更短的路径并更新表 4。更新后的表格为:
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
总权值 | 2 | 6 | 7 | 17 | 22 | 17+2 |
路径 | 0-1 | 0-2 | 0-1-3 | 0-1-3-4 | 0-1-3-5 | 0-1-3-4-6 |

图 6 最短路径 0-1-3-4-6
8) 从图 6 可以看到,只剩下顶点 0 到顶点 5 的最短路径尚未确定。从顶点 6 出发到达顶点 5 的路径是 0-1-3-4-6-5,对应的总权值为 25,大于表 5 中记录的 0-1-3-5 路径,因此 0-1-3-5 是顶点 0 到顶点 5 的最短路径。

图 7 最短路径 0-1-3-5
由此借助迪杰斯特拉算法,我们找出了顶点 0 到其它所有顶点的最短路径,如下表所示:
|
1
|
2
|
3
|
4
|
5
|
6
|
---|---|---|---|---|---|---|
总权值
|
2
|
6
|
7
|
17
|
22
|
19
|
路径
|
0-1
|
0-2
|
0-1-3
|
0-1-3-4
|
0-1-3-5
|
0-1-3-4-6
|
二、迪杰斯特拉算法的具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | V = 20 #顶点的最大个数 INFINITY = 65535 #设定一个最大值 P = [ 0 ] * V # 记录顶点 0 到各个顶点的最短的路径 D = [ 0 ] * V # 记录顶点 0 到各个顶点的总权值 class MGraph: vexs = [] * V #存储图中顶点数据 arcs = [[ 0 ] * V for i in range (V)] #二维列表,记录顶点之间的关系 vexnum = 0 #记录图的顶点数和弧(边)数 arcnum = 0 G = MGraph() #根据顶点本身数据,判断出顶点在二维数组中的位置 def LocateVex(G,v): #遍历一维数组,找到变量v for i in range (G.vexnum): if G.vexs[i] = = v: break #如果找不到,输出提示语句,返回-1 if i>G.vexnum: print ( "顶点输入有误" ) return - 1 return i #构造无向有权图 def CreateDG(G): print ( "输入图的顶点数和边数:" ,end = '') li = input ().split() G.vexnum = int (li[ 0 ]) G.arcnum = int (li[ 1 ]) print ( "输入各个顶点:" ,end = '') G.vexs = [ int (i) for i in input ().split()] for i in range (G.vexnum): for j in range (G.vexnum): G.arcs[i][j] = INFINITY print ( "输入各个边的数据:" ) for i in range (G.arcnum): li = input ().split() v1 = int (li[ 0 ]) v2 = int (li[ 1 ]) w = int (li[ 2 ]) n = LocateVex(G,v1) m = LocateVex(G,v2) if m = = - 1 or n = = - 1 : return G.arcs[n][m] = w G.arcs[m][n] = w CreateDG(G) #迪杰斯特拉算法,v0表示有向网中起始点所在数组中的下标 def Dijkstra_minTree(G,v0,P,D): #为各个顶点配置一个标记值,用于确认该顶点是否已经找到最短路径 final = [ 0 ] * V #对各数组进行初始化 for i in range (G.vexnum): D[i] = G.arcs[v0][i] #由于以v0位下标的顶点为起始点,所以不用再判断 D[v0] = 0 final[v0] = 1 k = 0 for i in range (G.vexnum): low = INFINITY #选择到各顶点权值最小的顶点,即为本次能确定最短路径的顶点 for w in range (G.vexnum): if not final[w]: if D[w] < low: k = w low = D[w] #设置该顶点的标志位为1,避免下次重复判断 final[k] = 1 #对v0到各顶点的权值进行更新 for w in range (G.vexnum): if not final[w] and (low + G.arcs[k][w]<D[w]): D[w] = low + G.arcs[k][w] P[w] = k #记录各个最短路径上存在的顶点 Dijkstra_minTree(G, 0 ,P,D) print ( "最短路径为:" ) for i in range ( 1 ,G.vexnum): print ( "%d - %d的最短路径中的顶点有:" % (i, 0 ),end = '') print ( "%d-" % (i),end = '') j = i #由于每一段最短路径上都记录着经过的顶点,所以采用嵌套的方式输出即可得到各个最短路径上的所有顶点 while P[j] ! = 0 : print ( "%d-" % (P[j]),end = '') j = P[j] print ( "0" ) print ( "源点到各顶点的最短路径长度为:" ) for i in range ( 1 ,G.vexnum): print ( "%d - %d : %d" % (G.vexs[ 0 ], G.vexs[i], D[i])) |
自动化学习。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2018-10-26 路由系统
2018-10-26 jinja模板语言