QQ登录

只需要一步,快速开始

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

最短路径算法Python代码

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

1186

主题

4

听众

2923

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |正序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。& u3 J8 }- c3 i6 k  k7 q2 f

; I$ @4 o- s$ r+ g; P9 Z2 T; v## 1. Dijkstra 算法) G+ [4 }% R' [; m5 d0 D

( t' v, |/ [! b. `* ]4 [. V/ ]Dijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。
( f. d7 _8 ?: \$ C+ E, a4 b1 O
! H1 Z8 p; L, S### 原理步骤
: P: Y: _  f0 }0 I
& P8 J% p2 a6 p1. **初始化**:
. @# c% m' T4 c   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。
5 Z4 z1 u# g) y7 Z$ E: H   - 初始化一个空的优先队列,用于存储待处理的节点。$ H2 q0 {$ @& @+ I: ?
$ K" O8 e+ K) t8 z+ Z( {
2. **处理节点**:, B; {/ a5 j$ ^; q1 w2 c
   - 从优先队列中选取距离最小的节点作为当前节点。: y  o+ t# o( z0 j2 Q4 f
   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。
5 F" P; A- |) M3 G* Q) @% i) |
# H5 a$ a3 t0 k* a3. **重复处理**:) _4 V9 [9 b( h; H8 S- Y. {% ~; V
   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。( Y& V$ T% T7 Z7 {( k9 j
2 P# V: Z) j, v; l4 \
### 示例代码/ r- ?8 k4 z8 F& r9 T( w  J

% }. m6 Z) y- E6 K+ G4 c7 I```python
1 {+ `' \( U, O4 n' v8 wimport heapq# p" a6 H$ A1 O! L7 E$ |
5 Z. f' N$ @0 }$ J5 z: r- c! ?2 p. X( l
def dijkstra(graph, start):
# p0 c+ Z8 Q( a1 U- B) t    # 图的表示为字典,键为节点,值为邻接节点及其边权
( M5 o# I3 |5 K5 E$ \    queue = []
  B5 S% S0 J9 d0 ~    distances = {node: float('inf') for node in graph}
0 A; G) J! J& v3 F, h    distances[start] = 0
5 D2 n; a) Q# P( E  C0 g% M    heapq.heappush(queue, (0, start))  # (距离, 节点)8 T: k  O- x( U$ r  e5 \, K' }
* H- ]% K6 T' b( y3 [
    while queue:
" u7 K* E5 X7 B        current_distance, current_node = heapq.heappop(queue)  i+ d" x; k: G8 N+ [: R
" E. S, p  Y& b4 ]7 q& {2 m
        # 只处理当前节点的最短距离) L" \6 s5 F/ m
        if current_distance > distances[current_node]:
+ Q1 |8 j8 n( U. y/ C            continue3 Q) t( ~5 i* K$ D% e
1 t& P5 I! Y: U8 w
        for neighbor, weight in graph[current_node].items():
  @' |- t) |9 k5 D! a            distance = current_distance + weight
3 I! d/ M' d/ `+ C% U; z  b8 u- q
0 Z0 ]( Q5 s. w            # 更新邻接节点的距离5 U/ w& x& l; {1 j1 ]2 L
            if distance < distances[neighbor]:4 ]2 [/ r' T2 N
                distances[neighbor] = distance9 y9 t4 s( W  H) M0 ^! o& h
                heapq.heappush(queue, (distance, neighbor))
$ V1 \6 e2 u4 j- \
/ O& x5 }& J5 Y    return distances
8 H8 q- r7 I1 C3 j1 X* S
8 o0 f% `; N) W1 }4 l2 v3 k# 示例图
5 T! H. C8 A: \7 Y4 X2 V- D/ qgraph = {4 S8 I7 J8 p) c! }3 @. v2 }. c4 j
    'A': {'B': 1, 'C': 4},7 A, I; J$ E+ j2 z7 k
    'B': {'A': 1, 'C': 2, 'D': 5},
* S! C# Q: R) [3 W" V    'C': {'A': 4, 'B': 2, 'D': 1},: L  Q" Y. O5 h* h7 `- m0 `
    'D': {'B': 5, 'C': 1},& K# e# f, Q6 W- ^
}# v+ M1 Z) V# [/ i
+ g; l+ {% z# B- X
start_node = 'A'0 `; W3 j) K7 v& z4 }# x
shortest_paths = dijkstra(graph, start_node)7 U) _- l- F# z! C
print(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}& _  M, C1 ~5 a6 ?! _+ q
```, F" l8 _0 o9 A7 d# r4 H/ a

, \' n" e  P5 v# v4 C# M8 |( }( I## 2. Bellman-Ford 算法' r% O: x0 w. Q: Y6 R- y

# C0 B- u9 Y( L& [/ TBellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。
. c8 a  Z0 E: Q
& X3 O/ Y9 L7 v' \/ h' _### 原理步骤6 g3 t! w; b# H' _# G. n. \, {0 h
8 E5 F' y& G9 z
1. **初始化**:4 @1 n$ l7 |- `. S9 d/ Z
   - 设置源节点到自己的距离为0,其他节点为无穷大。6 O8 q1 [) J1 k7 G/ \& q
0 G& b9 T" @8 K: [7 p2 {& w
2. **松弛操作**:
+ l' S- w8 k& X6 U, p, d$ f   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。
* G7 p" \; q- w  c8 Y! B2 u3 t% ]2 h7 @
3. **检查负权回路**:
5 K7 {& D3 Q7 |' `; k1 ?   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。
. J. h6 h- @) F5 D/ I. G# x4 W
6 Z7 E4 S, l( E3 U2 n1 o0 m### 示例代码& B- d9 D1 \/ r- j
, Y1 T+ f7 D; D+ l; {+ K; E
```python
9 x- J/ F8 r8 ^# xdef bellman_ford(graph, start):
7 d9 d* j" }* P6 T; E3 f8 G# f, d    # 初始化距离( C) |8 J$ s( k4 D% q, k3 N
    distances = {node: float('inf') for node in graph}4 g6 G6 i: Q4 W  n+ t, P8 Y  a
    distances[start] = 0
+ J3 [, i8 b+ {" G
. V3 H5 @) z' r; y4 v0 O    # 松弛操作
; {4 p: f( t( n6 w: }1 z    for _ in range(len(graph) - 1):: M$ Y! [- F4 T2 i0 ~
        for u in graph:
9 r* V( ^# s. u6 g7 D            for v, weight in graph[u].items():% I; t. {; i1 `5 V! J
                if distances[u] + weight < distances[v]:
8 z1 P. P9 W6 R$ z                    distances[v] = distances[u] + weight
' h+ a$ z1 p% S6 F. r
/ `; [: `  l# g    # 检查负权回路) v! Z- m4 [# e3 m: G9 X- i
    for u in graph:
3 q" y* h6 L4 w, s# O        for v, weight in graph[u].items():
9 M0 m$ z- d: D            if distances[u] + weight < distances[v]:2 k$ G1 l1 v6 `- {$ O* o
                raise ValueError("Graph contains a negative weight cycle"). ~2 [  }& t) }: B: ?* X
& F% l$ v8 U( j
    return distances
5 G1 Q! g% W3 \( k! \9 ?$ B6 x. R) z& X
# 示例图(带有负权边)9 d" K1 h, V2 N( L! G; c; w
graph_with_negative_weight = {
8 C* N( P# \* P7 r6 E# D    'A': {'B': 1, 'C': 4},
- u0 R, a( G* }+ G) i: [, g    'B': {'C': -3, 'D': 2},
! o/ ^0 Y1 c, v- @    'C': {},+ k1 s1 |  G6 _# K2 X4 l$ h" n. O' k
    'D': {'A': -1}4 k; S" T8 \) x% N
}, x8 m2 y* D6 K8 a4 d
2 X4 ]- A0 ?, z) h: y% v
start_node = 'A', d' b5 K0 ^7 Q0 p! D- i% Z' `
shortest_paths = bellman_ford(graph_with_negative_weight, start_node); C( p, v$ U& e( Y
print(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}
6 c. _3 w* I  }3 r1 a. B, y```. }7 U1 {/ n, g3 |& d5 Y
8 D1 L: _: b0 }8 n
## 3. Floyd-Warshall 算法
; l1 j7 v9 e: e/ g0 ], g% x0 z; u
  M/ u" e- \& l' D) ^Floyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。
3 H. N/ R% a' D8 ]& H
: l& @* W' b$ r, K### 原理步骤3 Z1 ?5 M, d( h# d- j3 P
" J8 ]& y! v4 x% I7 v0 L
1. **初始化**:% `% D0 u9 B4 H6 p
   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。
7 `$ ^! k$ F/ m+ A  o$ M  I
# y6 E4 V! V3 ]( _8 {2. **更新路径**:; p0 A/ }: x* ]/ D& ]5 I
   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。
( P/ m$ S! W) L* B; t3 s
+ y9 y* [0 A" Q4 [0 K- B3. **输出结果**:( p' @* D4 z8 i, m& j- z: C7 f
   - 最终得到的矩阵即为每对节点之间的最短路径长度。
, ~! ]: \3 [0 D2 C$ z
1 J! _) z' @  t. ]+ s; A### 示例代码7 j0 @, t8 g+ g9 T/ E

5 u6 C5 J4 g/ Z; I, a* T3 i6 J+ @```python( w. ~" B# J9 L/ S9 T
def floyd_warshall(graph):
. r, r$ B* f+ a/ a5 W6 }    # 初始化距离矩阵
. K0 n) G1 d) e+ e; @1 m2 t4 i    nodes = list(graph.keys())- ^( n% N  S- ^0 k) S1 i4 P
    distances = {node: {n: float('inf') for n in nodes} for node in nodes}
2 O) i- h& \7 A9 S' c
7 m0 |8 o; C! X    for u in nodes:8 u4 D. L2 f; X) s* i# K
        distances[u][u] = 0  m8 n% Z* {  l, K
        for v, weight in graph[u].items():
, \5 [; n) K2 c, Z3 X            distances[u][v] = weight
- m5 n7 @" h8 c5 |2 t7 h. c  }
9 X. q" d1 N! l- o( G3 ^    # 更新路径9 p4 e" d, |' E6 T( n# E
    for k in nodes:
/ ]3 F1 z5 G1 `/ B3 d, L' N        for i in nodes:9 h- \7 j: i# F
            for j in nodes:
& j0 y) y& ]& i- H4 C                if distances[i][j] > distances[i][k] + distances[k][j]:
; ~( ?7 t! P1 _5 V( l5 S                    distances[i][j] = distances[i][k] + distances[k][j]& x! Z5 r! v. I; b

* d+ l$ G4 @  l, K6 F    return distances
) m  {1 K) D! E! L# L' }( r/ |4 O; {8 J8 B! h4 a, F' \( w, N9 d! |
# 示例图(可以含负权边)6 |& i! k+ u# l* j6 }
graph_for_floyd = {
4 O9 e9 V" Q6 E3 L! ]8 _    'A': {'B': 3, 'C': 8, 'D': -4},
# O) J! G/ ^) ?( d' k; a+ {0 b8 `    'B': {'C': 1, 'D': 7},
- \# {; w1 F1 |+ s8 X8 L# R+ E    'C': {'B': 4}," s' b. J6 z' N% C
    'D': {'A': 2, 'C': -5}
$ b6 s" Q1 i" ?4 J" [, B3 w6 A}; T( p! ^& ?2 A. V0 X9 Q

" w( R& @" X2 k. B* a3 W/ J+ rshortest_paths_matrix = floyd_warshall(graph_for_floyd)
' \* \6 |7 |+ K( \# f4 ~for row in shortest_paths_matrix.items():; z- {) A0 V! o* h7 L7 C
    print(row)
& A/ |% T" f4 ~3 J- ^1 C```
0 p! q! g& u1 M
. v3 b* P) s0 {4 _## 总结6 H) U( t3 V) U3 j2 d

# {! L- {; J/ s/ g# K- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。
# z) \* u1 j! h& Z! ^8 k% d5 y- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。! {( H8 u" x8 T' ~* [! ?6 E3 X9 r
- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。
* Z' F) S  @+ z. Q/ B
- o) |' @1 T8 e不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!
8 y9 }4 a# `4 j! ]5 p
& w+ F4 Z: Y+ h" H5 t
' Q+ v1 ^, N9 o$ f! Z) R$ f4 T4 s* ~0 N

最短路径算法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-24 22:15 , Processed in 0.409531 second(s), 55 queries .

回顶部