QQ登录

只需要一步,快速开始

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

最短路径算法Python代码

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

1189

主题

4

听众

2934

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。
- o% w2 U8 Y* `" Q
* ]8 y0 R2 K0 c( b( @## 1. Dijkstra 算法' j* Q+ k% ?$ ^' l- g

) }2 C9 X" w( O* B2 ]- Q" rDijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。& X5 M* z9 @$ {. q

# y* P4 [0 b0 w, F$ }### 原理步骤
6 C* S5 T' f3 U6 V0 X- K
2 D; g8 u$ r+ o# o$ [1. **初始化**:
2 D9 D$ k1 X. H( m6 \$ N: W% w8 a- f   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。. B& N3 C+ d* x4 M: L
   - 初始化一个空的优先队列,用于存储待处理的节点。
; v  z1 A4 ?9 t8 }
5 b: ^+ E3 w$ M, w# F2. **处理节点**:
# }2 N. D( y7 T0 x' S% u   - 从优先队列中选取距离最小的节点作为当前节点。
* o1 j% u6 Q8 J   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。
0 A5 n& D, g8 W* j+ T7 H
4 m9 O3 ~2 |9 M* r+ n% t3. **重复处理**:3 w4 J# T5 q- v0 j8 _4 P
   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。
; V  v# B3 f, @0 l/ r. c5 l* F  j7 D: G  W
### 示例代码
8 r, w$ V; e0 r. Q1 C( d/ J$ i* y. Z/ U7 [/ E
```python
7 F( `) X5 d" T* ~' _# timport heapq4 H2 H1 q( P9 b/ |4 Q

& R  M5 V6 N2 g% t  C" idef dijkstra(graph, start):
/ Z# m+ n6 N3 ~# [1 a    # 图的表示为字典,键为节点,值为邻接节点及其边权: P# m0 e; R& H# v2 a
    queue = []& Y2 j- s* M  |7 Y( n, y) b0 g
    distances = {node: float('inf') for node in graph}& {4 `0 K8 g8 S$ v- A0 J6 k
    distances[start] = 0
, C/ p- E# K, d6 g    heapq.heappush(queue, (0, start))  # (距离, 节点)
/ O4 @2 u( B' W) W$ R7 e* p
' s; r- x3 S- H4 V5 I" F) R    while queue:3 t- o# \. ]3 ~8 N( ?6 N
        current_distance, current_node = heapq.heappop(queue)
- y# g. F& {8 V/ X/ y5 t; f7 D9 ^& p6 T1 }& _# j* N
        # 只处理当前节点的最短距离
" Q# a, q, Y5 \5 T0 ^        if current_distance > distances[current_node]:
6 _2 D% J3 |6 k  p            continue7 y$ n* q! u. ^) D, j5 T* C
/ P8 e3 k9 H  |* ~) A
        for neighbor, weight in graph[current_node].items():
& d3 k9 s# F( Z' @            distance = current_distance + weight
" ~3 f9 ^9 ?# |) {4 L) |
+ G6 T$ f+ s2 u0 M2 M, M            # 更新邻接节点的距离" H2 L4 d; Z: \: ^
            if distance < distances[neighbor]:
$ {; N+ w" e8 F' \. V                distances[neighbor] = distance
6 E) E. I, P, ^& j; W                heapq.heappush(queue, (distance, neighbor))
! M$ y! r" f5 p$ c% n  U6 L% t# P9 p  A
    return distances, c( ]6 H# f" P" Q7 c' ^

3 `! f( [. x2 N0 @# 示例图
5 P/ Z0 e  r; jgraph = {
  D0 Q( w" X1 x4 ]/ g+ j! T1 _    'A': {'B': 1, 'C': 4},
, t  _+ n' b4 w3 Z& V" I* }! Q    'B': {'A': 1, 'C': 2, 'D': 5},
/ N9 C; k5 u: |4 b6 a7 i    'C': {'A': 4, 'B': 2, 'D': 1},' T! v" s3 L6 [! |  u7 _
    'D': {'B': 5, 'C': 1},; e; x$ f) r0 X. P: S+ w
}
; _1 |: _" b8 |8 [* b, e. P2 k& N3 ~  R$ ^
start_node = 'A', F, D0 U- y* U
shortest_paths = dijkstra(graph, start_node)
$ _$ b8 l$ _' d' h# h0 Zprint(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}
) c8 N/ G6 }# o) A( P$ A```
; S) ?/ \# x- C) t- `& M7 v, d4 n* U. X! P3 G' q3 }9 ^
## 2. Bellman-Ford 算法
# W8 c% [6 f7 ^* F$ M; K
$ M- \9 {  Q7 h4 N8 t; G. m7 yBellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。- i- S  a* l% ~! n4 |2 ~
" w4 p8 d" \9 ^4 H
### 原理步骤
/ D# d- Z. l8 A& m7 A% o: b2 b+ M. P' C9 N. x: v5 K
1. **初始化**:
+ s5 E8 V; b( \/ p& ?* M   - 设置源节点到自己的距离为0,其他节点为无穷大。
, d$ O: i' L- `7 e/ G* X8 n; G+ r! W$ u" o' A5 B
2. **松弛操作**:" v% P1 t2 v3 Z/ g) T* r
   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。( E, x4 A) ]: ^

. G9 s* U% ~: B5 x3. **检查负权回路**:, z6 @  m, f4 D2 E- q+ p+ {6 F
   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。0 T- P$ d# I* t+ g9 V) d  Q

# O/ e+ d' T) ^( w! b# O- Q### 示例代码$ ]* w" n5 W& O7 R) j9 ?

5 h7 t( k) j: h# E```python
1 ~! M. K9 L2 ?4 Fdef bellman_ford(graph, start):
* X; f) ?) l1 ]/ R    # 初始化距离4 G( S( n" q$ N; a' r+ X
    distances = {node: float('inf') for node in graph}0 U, X7 D9 q& C/ v+ e  I
    distances[start] = 0
0 p4 v  E' k& Z2 [9 g5 H9 v! J0 A$ j3 b) h2 c! v" T$ Q+ r5 Y
    # 松弛操作: [- ~1 J$ ?1 t8 B
    for _ in range(len(graph) - 1):
" P" n' i3 L5 O9 h$ e  s! m        for u in graph:' J. O$ ]& F: l3 q
            for v, weight in graph[u].items():
( L$ ?& U# m7 w9 ~+ y                if distances[u] + weight < distances[v]:8 S3 G7 T) U2 _- A. S
                    distances[v] = distances[u] + weight8 ]/ d9 u9 y9 W$ M
/ T9 w4 ?0 B/ [* j7 C
    # 检查负权回路3 m2 A: W9 \& z9 ^' s
    for u in graph:5 \; ?( c7 {4 B
        for v, weight in graph[u].items():( f8 c9 z- f4 H; n; {
            if distances[u] + weight < distances[v]:: [2 u& N# O* U; j
                raise ValueError("Graph contains a negative weight cycle")
# ]# @1 r3 i; ?9 J9 b. n8 C, D; q0 V9 J
    return distances- R& C3 t; e" k
; s( B/ _' k3 r. T  P
# 示例图(带有负权边)
5 r% U( h# H$ M' |graph_with_negative_weight = {
# O8 {. j( e( m& J. l: a1 N2 t    'A': {'B': 1, 'C': 4},/ o* {+ e8 B( {8 y1 v, G! S
    'B': {'C': -3, 'D': 2},4 }9 T5 H2 ~( d) O3 R
    'C': {},
8 q9 C' Y& h- }$ f    'D': {'A': -1}
7 Y. Y  c* y* ]}
1 ]- V6 Q' W$ k+ O
8 ~2 u& R; i& ^! Gstart_node = 'A'9 C7 n; l- @- U: n: `/ J3 i, w& l
shortest_paths = bellman_ford(graph_with_negative_weight, start_node)
% M3 E& h( G5 R* |1 dprint(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}
+ W9 Q! v  n2 h, J7 u+ y2 x' m```
" C9 t2 o+ p4 m2 c8 L( k6 y7 K2 A. e7 [8 w
## 3. Floyd-Warshall 算法8 m) z( ]% I3 x: ]$ |( w
7 h6 O( T+ g7 D  L( V) ?
Floyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。
3 h! ?8 g9 ]' R4 P5 \. i# K+ R4 I1 m
### 原理步骤
' O8 [3 Z8 z3 C/ z& {( t
) H. L9 ?  b* k3 D; `+ f9 ~. p. b1. **初始化**:1 f# z4 Q" J) G3 h
   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。
0 [$ b; o0 C4 X4 M
, u9 I( A9 R& ]. E0 }8 K: L2. **更新路径**:' ?6 R) q6 X6 H* W
   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。& j3 O1 q9 B* _0 [1 }9 \

; x+ d/ T- u- Y* i) D! g& i3. **输出结果**:
6 j% i1 e+ }) t) Y" p% f6 S   - 最终得到的矩阵即为每对节点之间的最短路径长度。
& x* }5 l) w" z' H, ?0 i6 b# u7 L! [- e3 v: y
### 示例代码$ y4 T+ M, U3 \

: H+ Q; `& Y( @" g```python' n9 S+ ~+ d' W+ k! H: ^3 M5 E
def floyd_warshall(graph):+ I' b3 i0 Z& q/ N
    # 初始化距离矩阵
5 `. p2 o4 J9 E( L) \+ [- c    nodes = list(graph.keys())3 W! t6 Q* Q- U0 f
    distances = {node: {n: float('inf') for n in nodes} for node in nodes}
# K0 Q( U; J) s: U$ J9 Q1 g9 u- d/ P1 o3 X
    for u in nodes:$ R' ?) Z9 b- r: R6 H7 A
        distances[u][u] = 02 C, n$ v/ M8 S. J/ ^) g4 g& V
        for v, weight in graph[u].items():
, g( }  K1 Q0 Q            distances[u][v] = weight" r" p% y4 g! K

* H' l. `, s" H5 O. D2 u+ S    # 更新路径7 b+ E) Y$ g# z8 I- Y
    for k in nodes:
" V  [* m# v5 u. L: o; h        for i in nodes:
0 V2 E5 E, ^$ C" M# q# r! L9 ~0 Z            for j in nodes:2 J, Z1 b$ ~) f( }* v9 |
                if distances[i][j] > distances[i][k] + distances[k][j]:
0 o, U* `6 [: N& n" G' G) s                    distances[i][j] = distances[i][k] + distances[k][j]
! l/ W8 h; c4 q" `7 h; l1 J  `( }7 D
# l- Y! ^( P* C- ?4 g    return distances
# P& {. k" v9 G2 L6 p, l0 a7 q
& {! w% }6 {+ c2 \# 示例图(可以含负权边)
8 J2 j4 b: Y1 H2 D7 Cgraph_for_floyd = {, |$ v9 h: _( G& K2 v: q
    'A': {'B': 3, 'C': 8, 'D': -4},
5 G  `* Z1 I8 M, }    'B': {'C': 1, 'D': 7},- l+ l( Y) K. [1 m
    'C': {'B': 4},
5 N5 d6 c* ~; p    'D': {'A': 2, 'C': -5}
# |. b* R, G4 v$ r. B}' W9 |, b8 m! K% L- [6 `! ?: ~
. R( {8 d- r- K7 A' z
shortest_paths_matrix = floyd_warshall(graph_for_floyd): p+ t1 F" l8 R6 i  \4 @- e3 M
for row in shortest_paths_matrix.items():
) w) w0 }* L* H* ^    print(row)9 K! j; T) \8 U* v
```2 T. {# v7 `, ^) y, {( h* L- V6 E
8 w: \, G, u  _. m4 J) k: j/ F; M
## 总结" v2 e& ^8 a7 ]/ C3 w1 K7 T

0 S. d( e. C. F+ W! f2 ?1 D) c- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。
7 a/ H4 X! |3 ?' u9 h- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。( q+ \" X# e! W
- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。/ {4 x  b: d1 g" U! e8 _  N" x

7 y# B8 i% a, f+ u, H: h5 q+ j不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!# K/ ~) C) z$ ]/ s0 T
" W4 t9 W2 Q% C* \! i2 I
. b; S# _/ Y" h( c

. R0 n4 i' O: l) ?6 D0 ~

最短路径算法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-27 16:57 , Processed in 0.425871 second(s), 55 queries .

回顶部