QQ登录

只需要一步,快速开始

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

最短路径算法Python代码

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

1186

主题

4

听众

2923

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。
, k% b, y# l1 s8 L
8 R: [; V, S1 ]9 j: O## 1. Dijkstra 算法& ]' i; j% D2 D8 ?( R* @1 W8 E" x+ ?
) [0 X4 I/ |8 ?
Dijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。
4 m4 s0 O) W+ }9 Y$ F
% f7 b6 C: }: e### 原理步骤6 {8 I9 B! E6 k; ?; @

+ I6 ~5 h2 d! k2 S) ]1. **初始化**:3 h" x4 ^( ]% M& G
   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。
  i0 V& p6 U1 W* l7 e9 U( D   - 初始化一个空的优先队列,用于存储待处理的节点。
5 D5 g. }. l' d# b9 [1 @+ W0 Y
/ H0 G0 z8 u8 q4 ?9 F2. **处理节点**:
! D% V6 T% B+ q. I" c# Y   - 从优先队列中选取距离最小的节点作为当前节点。
$ b7 Q  g# h) }8 |   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。; |" X. H8 _1 b% U1 D
& j. U% M' z0 p0 |, `; B" T; m
3. **重复处理**:
2 S( A' w2 [2 m  s! D   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。1 ~' r! J2 Z* ^! a( g
7 e! T1 T) m. n
### 示例代码
9 |7 ~6 I6 u& i! e" q9 J3 s9 ]$ t: a  W( t
```python8 o! }1 P$ O5 Y8 A
import heapq
# X, B% j; C5 R/ }5 e8 ]- U8 M# }$ V! }3 a( r5 P
def dijkstra(graph, start):/ ?* j( n2 V5 @; k' ~) l
    # 图的表示为字典,键为节点,值为邻接节点及其边权
3 N, W/ m  H: K& m% H% m    queue = []
' c1 i7 L1 ^% `* Y0 d    distances = {node: float('inf') for node in graph}
) f- _1 \. a0 K/ K, E3 p) k, Y) O    distances[start] = 0  ~# f7 k& S: U0 C1 i$ @
    heapq.heappush(queue, (0, start))  # (距离, 节点): T8 @8 U/ ?! @. @1 p

6 N; \2 O+ w( Z+ Y+ ^    while queue:
4 b* L9 l7 }5 e6 ^" U4 k        current_distance, current_node = heapq.heappop(queue)$ m* d) X! @' v  V0 M. s

. y& O- p  [9 Y) R! b        # 只处理当前节点的最短距离2 ]5 Y" H8 k' a/ k1 F, N! C1 E9 ?! R
        if current_distance > distances[current_node]:
; p6 b5 ^  }+ r7 f; c2 i            continue7 [7 k1 z+ k, U' B: U% {
, h! i0 z9 j, ~& x. g* x2 W
        for neighbor, weight in graph[current_node].items():0 s# V3 _6 y% D, ~" V
            distance = current_distance + weight
2 }& N& I: l/ m' Y. ]$ x- l8 K
' e1 C& I  \) D/ J; A& |            # 更新邻接节点的距离0 [! R/ ~% Z1 S: i- d
            if distance < distances[neighbor]:, \1 i2 }+ D# q4 B5 a
                distances[neighbor] = distance, H0 {' S0 _. h5 {6 {
                heapq.heappush(queue, (distance, neighbor))
2 M+ f, R# J. z% O* G, i+ \# M5 d* E* {
    return distances8 M7 h9 O! _# {7 c. P2 g
) f6 G- I" w' D  j% Q2 U& X$ q
# 示例图
) e$ ]) a4 r- ]3 O) }' F1 bgraph = {
1 D3 Z8 z0 F' f. B, s( N    'A': {'B': 1, 'C': 4},
! d* o0 j/ P8 j9 V( N! E% X3 z    'B': {'A': 1, 'C': 2, 'D': 5},0 R5 ?& u" r4 v/ N% `/ U' D
    'C': {'A': 4, 'B': 2, 'D': 1},
) n: o- |5 G/ g: Q    'D': {'B': 5, 'C': 1},' f) ?4 t+ U7 K, u  J0 A* o9 s
}; p$ B  U# @2 @! z0 z
: _$ L3 `  }! k5 ]2 o
start_node = 'A'
* y* z4 h. z* ?6 {$ Gshortest_paths = dijkstra(graph, start_node)
3 E$ Z* G8 J2 d3 O7 ^print(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}& u* O  c8 b. F
```
; `( {3 L# s& I2 o0 N
, O( d, ?" W, J" r6 c1 f## 2. Bellman-Ford 算法
. c! q2 o8 C% b# j4 ]8 @. D2 B
- ]. @$ z) W* a8 z% PBellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。: [* w2 W; j4 i5 F/ c
. m: w4 }) ?( s5 H7 d/ \
### 原理步骤( e1 o3 q3 n! z, D
2 H! M# B$ h& ^7 p. d4 Y. p
1. **初始化**:
" w% o# Z, i8 ^! X5 g, [. G   - 设置源节点到自己的距离为0,其他节点为无穷大。
8 v& i' f, w8 Y0 d+ }6 D3 ^9 z4 y. a" t9 }8 ?. s$ k
2. **松弛操作**:
  L& m2 F; x1 \5 a0 }5 s   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。
( R7 F5 L& h2 v. q' m, q: ^* V8 |+ f
3. **检查负权回路**:) I0 e! V. v: d7 p. }4 w
   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。
6 h4 D6 s; w& T% Z3 t& z, p
1 [0 k- h+ t% [; U### 示例代码. U$ V8 s# I% F/ I' ^* Z* z1 ~

7 w& M/ J0 i7 |$ q0 u```python
! s5 x; ~$ e3 Gdef bellman_ford(graph, start):9 k2 z  z  S- D& u+ |7 k% e& y3 M
    # 初始化距离7 j  X4 H! J; Y1 D" C* [: X
    distances = {node: float('inf') for node in graph}
/ o; \4 e6 Q7 k% o+ W$ p2 N+ h    distances[start] = 0
8 K0 M8 [5 [& B  i. a- K
' s6 U/ O; h; h7 L7 \# R    # 松弛操作
8 u$ K1 Z6 M8 `6 l  N% ]    for _ in range(len(graph) - 1):% O# Y4 R. _! y$ J
        for u in graph:
& ^: Q* n$ q9 r9 X! ~            for v, weight in graph[u].items():: a/ W2 I* ^6 F2 Z. f( Q
                if distances[u] + weight < distances[v]:, X, c& d7 r3 s0 f$ [
                    distances[v] = distances[u] + weight8 S( C8 }0 y) `7 j& u% D

; s7 l, P( ^/ G0 h$ o, I9 Z    # 检查负权回路
: h4 n8 m# E2 |/ r; a( y    for u in graph:
) s" X* {5 z/ [/ u' E        for v, weight in graph[u].items():. O# Z3 E# X8 a% \8 z+ {( T
            if distances[u] + weight < distances[v]:# a" E3 o0 ]) {) K1 c
                raise ValueError("Graph contains a negative weight cycle"), Z) v9 h, q/ L) T! h
2 L) |& u; n" a1 X' c( \7 T! K- z
    return distances8 c+ A" L0 E% u. j

+ X) u8 s$ J2 K$ ]9 I# 示例图(带有负权边)
8 n9 u6 b" [1 O7 s8 I* X8 Igraph_with_negative_weight = {
4 G; M$ q9 J" p  c3 I6 a2 ^+ w    'A': {'B': 1, 'C': 4},' L1 d; i  Y4 g$ K* L& o9 j
    'B': {'C': -3, 'D': 2},6 H* X; _/ P% z
    'C': {},
% P: s) @6 y$ G- a/ Y    'D': {'A': -1}$ r6 `9 r/ W: N6 |" D' t" m
}( b$ x  f5 Z" J$ Q. ]

0 I  a. q( V$ A9 d7 p. ^+ ]start_node = 'A'# P. l- Y9 M2 l. b  O: ?+ i
shortest_paths = bellman_ford(graph_with_negative_weight, start_node)
* H0 n2 z4 i+ e- H3 ?6 |8 k0 }print(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}
- n7 ^; P; G( f% a```
- C7 ]3 t( o( A$ @" W6 e3 i
3 \; E9 ]! u% d0 S& D) \7 h  \## 3. Floyd-Warshall 算法4 q8 Q# t! s* J5 b' ?7 d+ D

7 M' ~) `4 \( G. _- ]Floyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。
8 {6 W$ i6 p! U9 A# l7 T. p
$ ]' g* }8 M  |' s5 @3 K### 原理步骤& F  b, t9 A, F6 c1 P

* ]  n% t4 E5 P1 ^/ R1. **初始化**:0 E$ f/ v# P9 l
   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。* \7 U" l' M& {! D5 J7 o: C- x4 m

) a9 F$ J7 l/ n. ~3 r2 \2. **更新路径**:
4 F7 u8 G8 w* j- d5 a( ]3 a* W. y   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。
* z  N0 o* P! E2 A: A6 f) b! q
3 i& A( z; u" j; H* A: f3. **输出结果**:
; H7 g8 a' V3 l( G4 d& t5 }/ ^% z   - 最终得到的矩阵即为每对节点之间的最短路径长度。
( v2 T- y& R* L) O, X0 P3 @7 t0 ~
+ `8 e7 q/ x& S& z+ X; G+ ]### 示例代码  `# P/ a5 q: g! ^

0 a% q' Z7 L- @8 Z% Q& Z```python9 @/ h! t* Z* P: D
def floyd_warshall(graph):! ?* _/ H% n4 x5 @
    # 初始化距离矩阵
5 l7 k) G6 @' U9 W( x    nodes = list(graph.keys())  h7 `: o- s2 f5 e
    distances = {node: {n: float('inf') for n in nodes} for node in nodes}  X- |; ?0 C" M

7 m, K3 ~5 j9 B3 x4 }3 T# S) U% l    for u in nodes:
" s. C* e! z/ }# L( I1 }( ~        distances[u][u] = 06 c0 `/ P3 l7 P9 M: z4 F
        for v, weight in graph[u].items():
5 s# w6 [/ ?0 D3 O/ y# Y# D            distances[u][v] = weight
6 U! ~0 T5 z3 F( m5 J
4 V: @! w! f3 I. Z    # 更新路径
! M+ E& b( P# N" B  W    for k in nodes:
7 ]& m) R3 p. {5 \( p' ]        for i in nodes:
2 W; \1 H" p  j9 a7 J            for j in nodes:
$ O& [! n+ A3 j; E: M) W                if distances[i][j] > distances[i][k] + distances[k][j]:
6 g& r+ G5 W; J6 Q. I                    distances[i][j] = distances[i][k] + distances[k][j]
, @$ A3 y' V! [- a
$ b0 q5 A% k& ~' }4 W    return distances
1 h; p% V2 n3 g; K# I3 K1 r+ ^
. d, C8 A3 C6 t" t9 j# 示例图(可以含负权边)- @( o6 o) h( ^7 z0 p+ |# ~
graph_for_floyd = {
3 L! p6 Q8 Z/ f0 P# p$ |$ o    'A': {'B': 3, 'C': 8, 'D': -4},; f, M( M  \8 G5 z# q3 H) q- C) E7 C
    'B': {'C': 1, 'D': 7},
+ }5 r6 O+ W/ D0 ?    'C': {'B': 4},
/ k. j( f1 S) F+ @4 Z$ l+ n5 G    'D': {'A': 2, 'C': -5}8 e' P% ?% `% _) c
}3 w, ^, N& v8 M) T% M& u2 j$ v: ?  m

- S5 u( b: o1 k+ q9 u1 V1 e0 nshortest_paths_matrix = floyd_warshall(graph_for_floyd)
' ~3 [& V1 W  K9 Rfor row in shortest_paths_matrix.items():
5 U7 W) c( b% T+ {$ g    print(row)0 Q! k$ }" w6 s6 g" b% r
```
# M# |* W( v; V
2 \. p) }' k1 o* ?, b( v  p0 @## 总结5 d6 X8 p* ^. V2 b5 y
5 P3 d! W. ^( H2 O- j0 S2 `9 U- d* V4 x
- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。
1 c5 K9 b+ P7 e" ]3 j$ ~/ j1 D- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。( x9 h" D8 d% B) }& k  X
- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。; b. [1 Y* M' K6 r9 r
1 d6 J, x0 O9 t* ^8 ?9 X
不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!# t& }7 V; C) J8 |$ J) B

4 A: p7 E4 A3 o
; O$ n- k* l! J8 P: {4 @9 o8 e# \4 t9 A/ i  c" q0 n3 V$ d

最短路径算法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-4-25 12:07 , Processed in 0.458514 second(s), 54 queries .

回顶部