QQ登录

只需要一步,快速开始

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

最短路径算法Python代码

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

1189

主题

4

听众

2934

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。7 J! g. E) V( M6 z0 j

# w" `) S; K4 S/ o## 1. Dijkstra 算法
- V, H* A& Y5 [8 V% U9 ?
1 e6 t  L9 m$ ]5 s  y6 s2 p6 z- J  W9 tDijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。
; A- R  C. H0 {$ V6 T' a7 f% i- h1 a* \: b
### 原理步骤4 S* U- o- }9 w% E% m7 U- C4 r0 v. q
8 M* u; ^0 y0 D# Y! r: k% m6 ]
1. **初始化**:
! j/ ]- F  ]" n$ r1 h( _; H: b. X( A   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。8 d% Z! F9 r; z2 C6 i
   - 初始化一个空的优先队列,用于存储待处理的节点。( E4 F8 q1 G% I# s
* ~( Y7 U/ d5 ?6 A# R: I& ?9 ~
2. **处理节点**:8 @# ^4 X% W( t9 Z* h, i; y; V
   - 从优先队列中选取距离最小的节点作为当前节点。
# e) v4 t& D% S6 {( a& _9 C   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。* Q, H6 O4 x! h2 U8 ]

: N' g# i+ ~* g' ^* C/ X* C3. **重复处理**:) r0 d' T. M1 g
   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。. W- w1 B# l# _# _

5 k+ G* e: E& M' S5 {  R2 F" e& b( b### 示例代码$ b, s) [% }- b( D
% v) j7 l" F6 S7 X8 R) v* P
```python4 N9 p* j5 R* Y" [& P$ O2 ]
import heapq
7 s# {) S- a4 q% P
1 [- `) m$ a  V5 @2 \5 k9 @9 ndef dijkstra(graph, start):& I! x4 a1 k6 c) Y& T4 n
    # 图的表示为字典,键为节点,值为邻接节点及其边权
; U% Y8 ^6 v+ m6 L( W7 h" W    queue = []
4 Q$ |5 y& t$ w3 ^* T0 ~    distances = {node: float('inf') for node in graph}3 F% o: P( J7 _% p% b4 f
    distances[start] = 0
* i9 J3 ~1 T6 j% t    heapq.heappush(queue, (0, start))  # (距离, 节点)
; x+ G, t) C( _+ X. G, B
$ Z. @( P2 l3 `$ ^0 e    while queue:1 y, D; l7 G) i5 W
        current_distance, current_node = heapq.heappop(queue)
% ?; R7 G  e0 b* T
7 K7 |8 ]. O5 D; b5 }2 f        # 只处理当前节点的最短距离0 E3 c, M: u6 i* S' c% G
        if current_distance > distances[current_node]:
6 x* E0 f( G7 k& u) B' D; k            continue
  `# W/ N& L/ }( H' Y: D4 ?8 S5 P
  `& f8 v' Z' \+ K        for neighbor, weight in graph[current_node].items():+ _: {& N+ p2 _# C. z
            distance = current_distance + weight
, p' ]2 P9 @0 a  M/ [/ |6 }7 V/ r& o0 k, z$ g9 G3 O+ l
            # 更新邻接节点的距离% _* j5 r0 V- T) q
            if distance < distances[neighbor]:
% M! |, i1 z! v8 e- t' ^- |                distances[neighbor] = distance* _% a) ]" Y4 F0 T3 p2 c
                heapq.heappush(queue, (distance, neighbor))" W- A- u" R/ F0 c

8 ^* _, s4 u/ P$ F) w* d7 C    return distances
0 Q* f: c2 C" Z5 N8 N! F% T, G' l: T* v5 o$ y; W. x
# 示例图
* u% H9 c) o$ q6 v# R3 h, h+ egraph = {
2 C7 l& m" u2 u; g' b1 h    'A': {'B': 1, 'C': 4},6 Y5 F) q/ o" ~
    'B': {'A': 1, 'C': 2, 'D': 5},
- d* S6 q5 Q) w. g8 b; h( p    'C': {'A': 4, 'B': 2, 'D': 1},: a$ i6 ^8 o5 x5 G4 F1 q' ]
    'D': {'B': 5, 'C': 1},: X/ W1 q5 @- }: _! P3 J9 a
}
) `) M1 {) g( L* {; Y# N& i3 H+ p, ^$ W2 p
start_node = 'A'
2 S( v4 U7 _% l: r( z9 {shortest_paths = dijkstra(graph, start_node)
7 g) \+ C; Q0 }print(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}
% O9 ?4 Q# m3 f# O```, I# w" Z) E1 t/ D
) G( ]( |$ g$ `, y8 }
## 2. Bellman-Ford 算法( m+ I8 c9 w& s6 W) x' \
! j7 M% ^( U7 m2 e0 }, q# H, R3 W( i
Bellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。/ s9 b2 C- d0 z; _1 T7 m

  D  \" Y, |& S7 g, j$ E, G### 原理步骤
2 T4 R1 r7 ^9 K2 L5 i3 J- e
4 Z' F$ o, h7 d( o- b, `5 n: K2 F1. **初始化**:
' I( R( b) w6 s# \* \   - 设置源节点到自己的距离为0,其他节点为无穷大。$ S2 [5 h( V. {# E! G

& ~) _( M5 F& ?! G3 q2. **松弛操作**:
1 j7 h7 f+ y; c* V   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。: I' E) f2 }2 b* N

* c9 @. g, }+ L/ S0 p; S7 Y1 m% X3. **检查负权回路**:
! b9 i& t+ |- }) `4 u/ Z' O% n/ M  X" B   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。
# V& r0 y& P6 L: E9 F* p% S
: Q; t+ g* N$ L0 A+ w, \### 示例代码: q: t0 O- ^/ h

5 O. J( q! [$ j```python( L# U3 e5 e% X6 p! G) L0 T
def bellman_ford(graph, start):# i2 I- U3 f* z, N& N+ i1 D  J9 l
    # 初始化距离
) f6 b, }" ]0 K    distances = {node: float('inf') for node in graph}1 Y1 s; l! P4 _" v. V9 \+ D1 w
    distances[start] = 0
+ r5 L+ _+ j( i3 B5 n0 c& f. ~; D
5 w+ h% D6 O' f2 ~    # 松弛操作
5 J- S+ {- ~# Y0 J, G' R    for _ in range(len(graph) - 1):
+ J, z( ?* Y' d' [( X0 q; w1 M9 F        for u in graph:% B% d( I1 R4 h4 G: T& Y
            for v, weight in graph[u].items():9 J0 G8 v6 P7 x* y# t8 v
                if distances[u] + weight < distances[v]:+ K7 Z* ]9 V4 @/ ^6 G
                    distances[v] = distances[u] + weight$ [; W' e5 T. _# O
' [" R4 Q' e( Z; w
    # 检查负权回路1 Q/ u$ Q2 K' p' s: V/ K' ]
    for u in graph:. K& r3 l4 y  G/ q% Y  f
        for v, weight in graph[u].items():2 s  U' H% T) t: m1 B
            if distances[u] + weight < distances[v]:4 L) z1 l6 m8 ~1 b( c! L
                raise ValueError("Graph contains a negative weight cycle")
4 Q% y+ O: q# D+ M% g
# }2 v8 R3 W& a( \: w" c    return distances
# d% O' h! N1 v) l6 k2 ~  E8 `
1 O5 m+ r0 l) M* O" }5 u: A1 f% f# 示例图(带有负权边)! n/ h7 R' A/ K2 B- x8 h
graph_with_negative_weight = {
% q# u. ~6 Q4 a; i5 h7 V& u    'A': {'B': 1, 'C': 4},
1 B( g* F8 S+ U$ Z* l' X    'B': {'C': -3, 'D': 2},2 S% B2 T" ~, I' }" G
    'C': {},) m( b$ u# a) U- d/ |5 V9 x; U
    'D': {'A': -1}. y/ i% o5 Z( M% b% T3 [9 h
}
4 X6 z, n( M: G. K( B
( B0 k3 B0 I0 \6 Zstart_node = 'A'
' o8 S( s9 E* c, ~shortest_paths = bellman_ford(graph_with_negative_weight, start_node)4 ~) c3 v* X4 X! U9 W8 R
print(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}
1 B6 _3 |/ ^& g& _8 @```
' A7 V# ^5 `5 R8 S6 ~: J
# c, ~2 ~. ]: E; e& t/ d: L& B: t$ o## 3. Floyd-Warshall 算法
  O6 a$ ~2 G& l0 h  D7 Q/ Q" W6 }! {3 A2 q
Floyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。
+ I% Z+ l1 R( U, A; a9 _8 r# ]7 Z' V0 n2 I6 f# d3 j
### 原理步骤
! n3 u7 X9 v% F- q4 g- f! H( D* Q. t6 F, n( L1 u. i
1. **初始化**:
& S6 V6 \( _% P5 x; V. Q* X* [' q! j   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。
- P5 D1 X2 P2 D9 a$ n
2 s/ M/ ?! I4 e2 Q% b8 Q2. **更新路径**:( T* c3 B% s' B: {: p# S( v
   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。1 P% ]. Q1 J& e  K1 _5 t: A
5 q8 R1 P% [. _* ]) Z
3. **输出结果**:
0 r3 V+ X$ i& M4 z" d   - 最终得到的矩阵即为每对节点之间的最短路径长度。
7 }8 ~! X; e1 G' t
; q& y3 q- g; Y  ]7 E. X### 示例代码
7 r4 g1 P3 C! s! g3 K$ w
, ?9 `9 \9 O: r: f```python
. ^) a. C! S* ]def floyd_warshall(graph):8 ?) Q4 h8 N8 S( G3 ~
    # 初始化距离矩阵8 W# Y+ s* i( e
    nodes = list(graph.keys())& |5 l8 W' B1 W6 U7 w! A& ~- X! h
    distances = {node: {n: float('inf') for n in nodes} for node in nodes}
$ D# d8 M5 H. [( j+ }. N9 J/ ?5 D* b& e$ m6 m3 m. ?
    for u in nodes:
; U6 Z+ N8 Z$ v( L        distances[u][u] = 0
  o# _1 w: T7 C) j" ?3 T        for v, weight in graph[u].items():8 X7 h4 n9 Q; k5 x2 |
            distances[u][v] = weight3 e& w* m" M! `; j
# u$ V- b& H0 g# `! R2 r3 X
    # 更新路径
1 u  U$ I  @% g& G. o9 W    for k in nodes:
, x- P( W2 _5 }  z5 ~        for i in nodes:
# g- ^  z% K) X) H* r  t* R& B            for j in nodes:  V- L8 B  m/ O* u# _6 ]7 |
                if distances[i][j] > distances[i][k] + distances[k][j]:4 T% _" T2 {/ w& U* p
                    distances[i][j] = distances[i][k] + distances[k][j]
% F- j, \! R: R/ e& z# O8 `* v$ o+ J, F  q$ r
    return distances
6 _3 X. o0 ]6 a. e% R$ o+ ~& Z5 I6 G3 n8 ^
# 示例图(可以含负权边)
. I4 J7 m3 k2 H+ Q# ugraph_for_floyd = {( m  Y4 F  F, G6 {/ N% |0 y
    'A': {'B': 3, 'C': 8, 'D': -4},4 f; O7 N% p. ]4 y& d
    'B': {'C': 1, 'D': 7},
( v, }" r* {7 m    'C': {'B': 4},
1 g# d) p' w! Q* o* Y+ Q    'D': {'A': 2, 'C': -5}
3 o- a4 G# F1 g5 o6 X, o& P. w}
/ o5 h: H5 f; C* @. ~' O3 p3 M  [2 W2 p
shortest_paths_matrix = floyd_warshall(graph_for_floyd)/ N% B8 t/ A1 S! t" f% S8 ~7 i
for row in shortest_paths_matrix.items():
2 _$ M* `1 a6 n    print(row)8 j. x( _9 `- ]6 a3 t/ e1 j- i6 w4 y
```
0 p" `0 j* I# t
7 J0 J) `3 G* P2 ^5 D, Y7 B% ~; S## 总结
2 Y' E6 J) t5 m7 w/ |4 I3 v: R9 X& l  e0 {0 `* r
- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。
! c, b# m6 k# `, G1 Z/ c6 A, _- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。
, l) w' k+ `" @! e! U  E1 f( i( V& b- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。) G4 t' ^: v% ?9 K8 e, {
# N& g- x& A  K# {5 i. m# z* @
不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!- d/ E- |4 _, E9 s2 W

1 H2 e6 c2 O6 A* f" d3 w; h; ?1 ]1 h1 ]9 V- V+ h4 ^+ i8 [/ y& j

# S0 @4 o8 k% l  y& M

最短路径算法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 11:30 , Processed in 0.543977 second(s), 54 queries .

回顶部