QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2450|回复: 0
打印 上一主题 下一主题

最短路径算法Python代码

[复制链接]
字体大小: 正常 放大

1189

主题

4

听众

2934

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。  b+ y/ y3 z$ R5 m9 h
) p& T) V; v  j4 U) P# \$ F  I5 ?) P6 ~
## 1. Dijkstra 算法
, ]9 C8 K$ R6 x: c: j8 }- w7 d( x& A  y4 [6 @# T: e* J4 t
Dijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。5 X: P: i" ?2 G
' Y! i4 s# Y7 c" S# H' |
### 原理步骤4 y# m9 O3 z, \) {9 G# u2 s
7 W, d% v6 X6 k7 q
1. **初始化**:
- Z$ M7 V/ ?7 i9 X   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。
) B0 z& U- V: }4 O) B7 }3 J! e   - 初始化一个空的优先队列,用于存储待处理的节点。
2 c) B+ `( l  |% T, t
9 ~) ]0 K( G& _' Z# b' ^& O+ V( N2. **处理节点**:+ D+ i& e6 j9 ^% s' ?: X
   - 从优先队列中选取距离最小的节点作为当前节点。& C; Z3 n+ i. ^2 z: x
   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。
# T# G  s8 M7 [: n  L
: B# p6 m7 a- ?2 U3. **重复处理**:  ^  T5 e' K# N! G
   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。
+ Q+ Q8 A) B& c$ K! W' @
4 G6 t# v* d- O5 u& d### 示例代码
9 B  p4 I& o9 k! [  Z( V, _5 f$ R7 O+ J, C1 A: B
```python
& s+ F  X- `! A7 j  c2 o. qimport heapq
! M4 n( M5 l! O$ ?( k8 Q% F# u6 V9 I( ?) Q
def dijkstra(graph, start):9 }: p% x" }* _! A% p& o$ [
    # 图的表示为字典,键为节点,值为邻接节点及其边权
9 o5 ]) c4 C  I& ]0 G; ~, E1 Q    queue = []
2 j  |$ E. k4 n( t5 u. k5 X3 l9 E    distances = {node: float('inf') for node in graph}
. k, R% P8 O" c: V5 B    distances[start] = 0$ |2 S1 {, R. A; K/ `
    heapq.heappush(queue, (0, start))  # (距离, 节点)
; @1 T% W" I/ M( q# y* I- l" s
4 r' a- }3 M/ o& c$ u; ]: ~    while queue:
% [2 O8 B# M0 G6 U2 P. b' P5 ]        current_distance, current_node = heapq.heappop(queue)
2 G- T: `) P9 x) V: Y
1 ~/ ]# n( F" l9 y        # 只处理当前节点的最短距离$ J4 R% Z& j5 V2 Q0 Y
        if current_distance > distances[current_node]:
1 S" @& O$ C5 {+ C* s            continue# ]" m4 f# F: c8 ^% Z$ q
9 b1 J' X. x3 C; ?! C/ T
        for neighbor, weight in graph[current_node].items():9 y, {4 Y) Z7 \0 J5 L0 R" c
            distance = current_distance + weight  [" T" r% p5 F  i$ c( X
+ {: J$ V. |, n# K0 M- g/ a
            # 更新邻接节点的距离+ a) u7 N" T+ ?' ]: E1 E$ Y3 r
            if distance < distances[neighbor]:
% Z; Y7 o3 m! ?) o                distances[neighbor] = distance& ?2 G1 Y5 v  E# @7 _0 [% `6 T
                heapq.heappush(queue, (distance, neighbor))
8 x' @8 I+ F6 e. N& F; a" y* G
, k1 q# z& v7 E  V) W    return distances) ?9 T: G9 _7 n' W* v
1 s6 N, m) M: n4 C
# 示例图; p, P; ^6 }( }$ k5 _& t
graph = {+ n' x0 D% w' L8 P
    'A': {'B': 1, 'C': 4},  f* k: _# v  H% L5 H: x
    'B': {'A': 1, 'C': 2, 'D': 5},# V9 {( a+ J$ s& w3 _% P* X
    'C': {'A': 4, 'B': 2, 'D': 1},
1 n4 Z- X% X; H' U    'D': {'B': 5, 'C': 1},. M3 o: y: z! J; _8 [5 u% c
}
, P; `. }% a# F' b$ Z9 B. F5 f) z$ T/ b" o/ i. C+ X/ \+ V5 X
start_node = 'A'
+ \8 W: K+ `; o1 r+ n9 G2 E/ wshortest_paths = dijkstra(graph, start_node)& X  K" G9 L7 [. |0 L2 D
print(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}9 f# i+ N# g0 j- ~5 ?8 p( O
```
! W6 L, x$ F! v. O, A  C" f, c, f! P3 X; A( N; I% {* j" j  h) M
## 2. Bellman-Ford 算法
+ T% o4 M. g! G) b
4 K% u5 M2 ?! i- o9 W9 Q$ cBellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。
0 B4 R1 v8 d4 |$ E+ l
$ T0 Z8 O- I" x9 T  y9 ]5 L### 原理步骤
9 N. |' O: s+ B5 X
0 E+ z, `5 n2 b/ v% m5 w; t1. **初始化**:
7 C( Q9 f. V1 h. }: `   - 设置源节点到自己的距离为0,其他节点为无穷大。$ A! H$ j3 m. Q- |- i, r! H9 s4 L2 d

2 K# l; k5 y* o% i! R- G$ q5 W2. **松弛操作**:
0 B$ ?. R( V$ J: g   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。3 m8 n) l- X- s# T

" U8 u9 @- u" V& e3 |2 R" ~! q8 o3. **检查负权回路**:
3 Q# J1 P4 S; e% |/ H1 ^   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。
4 B" t! }' k; m" k9 u/ o& D) g
$ c3 y. A; F5 G2 p7 f- [5 h; M6 z### 示例代码# i- l9 [& ]. z3 y! b

/ x: A2 T2 D9 V' I; ?9 Z$ X```python, d; U) y' b/ f- @
def bellman_ford(graph, start):/ w5 {7 p$ {+ s7 L! s1 s( a; c+ b/ |
    # 初始化距离
9 t  g0 v8 \' R, c/ p$ ~; o    distances = {node: float('inf') for node in graph}/ n) N) w7 k3 B5 d+ Y7 s4 f
    distances[start] = 0- \9 V/ N$ B/ r2 ^, K7 o$ x
) c6 N& w  u8 l1 b. m$ O
    # 松弛操作" `5 |, U2 l' M6 t+ S
    for _ in range(len(graph) - 1):
+ y& h6 p: G: Y, H' |0 ^8 M' w+ x        for u in graph:3 o& ~3 A7 q% C# E( U
            for v, weight in graph[u].items():0 w1 {2 j1 ?9 z5 g. {$ w
                if distances[u] + weight < distances[v]:2 P: C6 p4 P& x) b% i7 ^0 q
                    distances[v] = distances[u] + weight
6 K/ ?- g8 X% \; G* |; P( e! H$ d8 T8 k, i8 z/ C' ]
    # 检查负权回路3 q8 X3 d. W0 A: w# t1 c
    for u in graph:- p  a7 ]" Y1 u, C% n
        for v, weight in graph[u].items():, l- }; ?+ {' b1 N/ ?% D7 [: a
            if distances[u] + weight < distances[v]:
; F2 D  y, H. X4 B                raise ValueError("Graph contains a negative weight cycle")
3 S) R. k0 O+ a! b
6 h( c6 Q$ {1 _8 y  N8 \8 f    return distances! `4 p7 |: e7 K

- }- y; s  i5 _7 W& Y6 w# 示例图(带有负权边)0 ?3 D; z' N* t, W" K- x
graph_with_negative_weight = {; y. P1 A4 f1 a3 U& K1 L, R& l0 I1 A
    'A': {'B': 1, 'C': 4},
4 W4 E+ b/ i( Q  l6 b9 c6 X, Z    'B': {'C': -3, 'D': 2},2 Y+ g) D( u  q; r
    'C': {},/ ^* g, t2 h+ j
    'D': {'A': -1}. q' [: F# k6 N5 B0 T" {( ~% S
}/ [$ D0 h1 N- i
" m3 W3 u0 n( R. |' p
start_node = 'A'
0 Z8 D) g1 t3 {3 E) o- r0 Rshortest_paths = bellman_ford(graph_with_negative_weight, start_node)
* h9 c7 o" s+ U- Q0 {& @print(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}
- u, S& g- n& A& Y& P```
( I( X2 R/ S" X! U- E* W
8 T( ?( S- u" R, v( T## 3. Floyd-Warshall 算法
; N5 y9 U2 @! c# U1 b8 @) N9 u' l! G& s8 Z
Floyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。
/ l2 I/ t1 ?/ C' {0 L' C! G
/ ]7 J# j+ t8 Y### 原理步骤
4 t6 U6 c8 N4 k0 S6 l  P
" E# A( X2 c6 a' x4 `4 I1. **初始化**:
, A3 f; {$ Z; `' Y' M   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。' F. j5 U. t3 B& M: w6 S

+ h4 p1 n" y. q7 ~8 q2 Z; k2. **更新路径**:
  e: ?3 f5 B) \7 ?4 X, |. f5 `   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。
2 r# H9 {$ G: b" a6 K: q
' E8 Y; V! S7 X; O7 s3. **输出结果**:
) B- t& s1 ]8 x2 B5 O! \   - 最终得到的矩阵即为每对节点之间的最短路径长度。: M) B8 @  |! g" [
+ N. F5 c4 \# o" A8 ]+ H
### 示例代码
: V6 Y, a& c4 K$ C& D8 B3 E, v  G# h: X+ H
```python
, b" x. s& }& k6 b' s/ z" Zdef floyd_warshall(graph):% u2 n" W1 t: A
    # 初始化距离矩阵. h+ B3 U* H- W/ \2 ~
    nodes = list(graph.keys())
9 C" |; I& K3 ^    distances = {node: {n: float('inf') for n in nodes} for node in nodes}# \3 N0 ?# S5 v  o1 X; @

& k$ B* i* j, f    for u in nodes:
& ~" |9 D7 T% F' ]1 |5 r* _. e- w        distances[u][u] = 0
  Q' d) Z$ O- A4 y( E5 N        for v, weight in graph[u].items():6 u! q2 p5 n: i5 L
            distances[u][v] = weight
0 Y( i" j! T, \1 V7 B
4 X9 o7 B# f5 H% e  i    # 更新路径
+ a+ p$ q  [5 l5 P' _    for k in nodes:
. n4 v6 W! M7 {- n: E        for i in nodes:; e/ s, l! p1 }) o
            for j in nodes:' C5 q# S  r/ Y, a% ^7 n
                if distances[i][j] > distances[i][k] + distances[k][j]:
) t4 G( v+ s, \: P1 O$ x                    distances[i][j] = distances[i][k] + distances[k][j]
8 t- B2 d. U$ L! q, S
. j) P; K1 y& N/ `    return distances, [5 ^( ^4 `9 s/ h4 g# `

; W- y) @8 V+ T; w; v; D# 示例图(可以含负权边)  H5 l" u8 e3 c7 j6 D
graph_for_floyd = {
9 Z6 N8 ?' g6 q+ d/ Q/ a    'A': {'B': 3, 'C': 8, 'D': -4},
* S0 N- x: D9 ^6 G+ ^8 j+ g' `    'B': {'C': 1, 'D': 7},
( H/ _' h5 {$ {4 k2 E    'C': {'B': 4},
- [# W, k* v, f5 `% S    'D': {'A': 2, 'C': -5}6 T' |$ _2 t# |1 t
}" F9 ?. \! ^6 \' a

6 ?; n7 x8 B# Y* ~shortest_paths_matrix = floyd_warshall(graph_for_floyd)) A: r. M/ L, `2 l. Y. G
for row in shortest_paths_matrix.items():1 |3 t" T3 V3 P) w  l
    print(row)$ k& |- p5 O5 D) H
```! w7 h% R* K6 }) {3 @6 H1 `" Q! h
1 a4 s! }1 \# ~, s( G/ o" [
## 总结
4 r2 A, W& U+ j* A0 s+ J$ E$ D" M2 n
- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。
& i& E0 B& X' G9 U" j6 k- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。
  x& g% T3 y. J( y9 B- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。* ]1 [7 t5 [. X
- O$ ~5 Y0 O# U4 a
不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!
3 E) r' L. Q; T# W8 \( |' n
# j, m7 P) O. z- @9 C8 U2 F$ S
- \' w5 n+ H- N, D/ q4 t, h8 \6 O
- F% y7 z- H2 J/ H% m, a

最短路径算法Python代码.docx

13.29 KB, 下载次数: 0, 下载积分: 体力 -2 点

售价: 2 点体力  [记录]  [购买]

zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-7-28 09:21 , Processed in 0.414392 second(s), 54 queries .

回顶部