QQ登录

只需要一步,快速开始

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

最短路径算法Python代码

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

1186

主题

4

听众

2923

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。" U) y' W, _9 [% k1 s( H) x
' N! p8 A4 T6 t: v( d: i# L
## 1. Dijkstra 算法+ k  O& x" J; H& H

# P6 n5 ^" F' @* |, I4 O. ]Dijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。: }0 e4 L1 s3 B5 R' N# f
; \5 u8 b# \# x  c5 A2 Z, F9 \
### 原理步骤$ I3 F- ^6 z7 K, k! K- i: q. `4 r9 L$ H
8 P0 L# W7 C9 [6 {# N
1. **初始化**:' ~0 j$ j2 V8 l9 y0 b  A
   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。6 \5 d' q& i5 D1 [; Y' P& \& ^
   - 初始化一个空的优先队列,用于存储待处理的节点。+ w5 P/ s$ [2 z# e6 |9 ~3 F; l
1 c9 q. _1 x, P) Y7 f# z# y* L
2. **处理节点**:
8 o9 C& ?2 i+ X   - 从优先队列中选取距离最小的节点作为当前节点。, U0 [- D, s7 f# F
   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。
! P. ?2 O0 J9 D, M9 C1 Z1 c! E: X: D1 C/ j' v, g$ ]
3. **重复处理**:! r: p$ J9 H6 D, h5 B9 @& n# p
   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。
# n1 W( A( k( _, r. ?- B5 l6 U
; t( e$ K' p4 ]! U  @0 c### 示例代码
" E0 S6 l/ v: M/ e) o0 l  Z: J: E' r* r" e
```python
. g3 R' S8 E& Z$ s' Ximport heapq! |1 Z. i  M9 Q* M% z- N2 _

7 l7 o* S' b  f, l5 T6 f  ndef dijkstra(graph, start):
1 L2 V; g6 a9 b$ @    # 图的表示为字典,键为节点,值为邻接节点及其边权
+ w" ?3 x+ T# W+ t+ Q    queue = []1 Y& |" s% t$ F. H4 w
    distances = {node: float('inf') for node in graph}
: ?3 b4 T* ?: ^8 \9 @    distances[start] = 0
  r0 r* d$ j% I0 V; [1 m- t    heapq.heappush(queue, (0, start))  # (距离, 节点)& Z- `, t% c- s: M' I
  K' G: q: t8 k& F9 H' b
    while queue:
3 N1 V5 Y4 Y1 }% I& \' s" ^        current_distance, current_node = heapq.heappop(queue)* h( V' X7 x) |7 z! l0 V

: c- @2 B- n* T9 m) b. c7 Y9 Y        # 只处理当前节点的最短距离/ ^3 Y3 q# p& M
        if current_distance > distances[current_node]:
9 m5 y) n. m3 P. M# `/ n/ a. V            continue
! E/ ~8 t4 W  Q0 }! _+ w( l
" O) g; I6 S( L! h        for neighbor, weight in graph[current_node].items():
5 U2 m) C; v) z1 W6 P            distance = current_distance + weight
5 u$ T) D8 n0 [; ]9 K' k$ p8 F0 z: C
            # 更新邻接节点的距离
% K7 f, S8 i5 w2 j* Q6 n, S            if distance < distances[neighbor]:! ?7 V; o. C8 [  M) M
                distances[neighbor] = distance
, L$ I" O/ I& m, t2 N3 C3 X- z                heapq.heappush(queue, (distance, neighbor))
& b, v+ B/ A! w9 ?, M4 S$ |" F+ U% L* [; O' @
    return distances) Q& c/ Y) b3 d3 e# G" n- N* C' N

& r9 N( d4 f8 f, }# 示例图
) H- Z, ?' v% ]graph = {" w/ m. u+ T2 X
    'A': {'B': 1, 'C': 4},
; b9 Z5 Z2 o2 @  ]* f    'B': {'A': 1, 'C': 2, 'D': 5},) s; R5 ?) T: t% b
    'C': {'A': 4, 'B': 2, 'D': 1},
* Y* ]" u. M. u    'D': {'B': 5, 'C': 1},
; e# C  Z: Y6 `}
/ _, z! x( g/ A. ]7 O, f
2 W. m; ~3 z5 L0 d- a& {: astart_node = 'A'
! A6 K, R" k/ C, J' r) w: Dshortest_paths = dijkstra(graph, start_node)
! X0 v8 M# B5 z& E" {5 t( tprint(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}
* {+ T. i- Y4 o3 g```
! Y) F4 `" y3 e1 L7 h' r+ _. E
. f0 c& d' _9 A& p" `9 `- ~( a## 2. Bellman-Ford 算法
" S- @$ |& H# Z  e! F* H$ y
- v* V9 Y% \, bBellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。) [  L, X0 K# U
2 ]/ Z" E, d+ i: h
### 原理步骤1 C- b! L: Z0 L
6 U6 s5 q  y4 l. t* A3 \/ W
1. **初始化**:
  Y' u9 K7 S9 a: }! T) S. T   - 设置源节点到自己的距离为0,其他节点为无穷大。( V- V5 h  l- _7 l/ Z% J: G
  e$ ]4 `, r7 F  n  H* F
2. **松弛操作**:
6 q% T* q" m9 W" U; c: m   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。
- `' h1 \; J5 h* j2 R/ h: y2 U
# n! Z* K/ t9 s. f' t3. **检查负权回路**:8 _2 Y* @1 l9 D8 K
   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。
. G3 \' |* q8 W/ h1 Y: @9 t& N+ o. _2 R/ O  z
### 示例代码
8 f. p, D8 F9 A
; Z  i" P$ V7 r" ?$ x; Q```python
' {, Y. r. G* v5 R) w2 C1 i$ Odef bellman_ford(graph, start):& z# l5 c2 X" A4 Z' a2 v) I
    # 初始化距离
1 f' c% J$ J5 A    distances = {node: float('inf') for node in graph}
; ~& L7 K6 o' M" Q! t: ]0 f    distances[start] = 0; S( y  A0 w  \" `2 U2 F

8 z) P) [+ A5 _/ n) G    # 松弛操作
! |" _0 p, {1 o/ s! u4 q  d0 V$ S& n    for _ in range(len(graph) - 1):
, u6 w4 P* M3 {9 G1 |: f        for u in graph:5 w, t/ O2 W9 H( }9 `
            for v, weight in graph[u].items():
. r6 @/ R9 }( s  y                if distances[u] + weight < distances[v]:) I: o  ?9 g) z, B5 n. t8 l$ F
                    distances[v] = distances[u] + weight
5 j, {( F0 D. D* Z2 r, {+ K
7 [) W7 R$ d; |; e2 U    # 检查负权回路
0 F! O% a' C- J. |# D% n8 d    for u in graph:
1 d# V; J& F1 n+ Q* o1 }        for v, weight in graph[u].items():
" P/ R3 x1 s; _9 ^9 w2 H            if distances[u] + weight < distances[v]:
; M# a) t9 O& q, d                raise ValueError("Graph contains a negative weight cycle")
( R2 w0 Y$ R) u2 f2 n5 Z8 d! P8 F' O( |& \1 N
    return distances  \  m+ \7 t4 J, p: e* ~, d

9 \+ B$ c: l. ~8 q; H# 示例图(带有负权边)$ W8 x7 u/ j. ]; p* X2 L
graph_with_negative_weight = {7 I3 g# ?/ w& [4 T! _; J& Z
    'A': {'B': 1, 'C': 4},
. |. e/ h; l5 y3 l, M& n0 [    'B': {'C': -3, 'D': 2},! A0 i& H* k9 V, s6 C
    'C': {},
6 T! q8 w* Y, c* j( }, k    'D': {'A': -1}8 H5 Q( B- X; A, O
}- v4 v; H2 V4 o2 W# p1 L4 s7 R

+ [5 r& p- M8 Z& dstart_node = 'A'
; n3 R' o; I0 ushortest_paths = bellman_ford(graph_with_negative_weight, start_node)6 T. y- f% y0 @5 u
print(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}6 E, R# W5 a& v  U; L
```
3 Z/ B- d" R9 s! ^
2 K8 c! L% w% X6 O## 3. Floyd-Warshall 算法
$ I# o0 z( E( N) F7 ]1 i' E" \6 n0 O4 L1 Y, t# S/ g* u
Floyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。
% G9 G1 o5 c2 s2 {4 g' @
) c8 M( `, B) Q+ N* o### 原理步骤
) W: T6 [% X4 m/ `, e, t
7 p: N  F! p' F0 i1. **初始化**:3 ]+ N+ Z+ n% Z3 L) a+ B9 R( p& V$ z
   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。  x1 y! a; ?, B% [6 z6 }: g' l
: A# V& a5 R: v4 k' _" ]
2. **更新路径**:/ [3 [2 ]- u7 x, j4 l0 h+ T
   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。7 M6 Z8 c0 q+ N, U# y3 |

* w0 x! z; q. `+ d8 E9 G3. **输出结果**:
. j' X( x# O& f, U   - 最终得到的矩阵即为每对节点之间的最短路径长度。
5 W( y6 `8 l1 `0 A) y1 a, o7 D
% e- i/ z" d( V" d1 e. X5 m# z### 示例代码
) Y" |- f/ S! O* q& Z, a( f; d5 z( e3 y% ~
```python
( W" E8 z; n1 L6 ~0 g1 U* [def floyd_warshall(graph):: ?! Q1 M" j6 }7 s) N
    # 初始化距离矩阵
% U& G, B3 W! N. ~* O& K5 }% I' |    nodes = list(graph.keys())
$ |. G( n2 K" k, t! R  X    distances = {node: {n: float('inf') for n in nodes} for node in nodes}) F& h' n+ U" j  N$ K6 L

& U3 z( O$ g" R2 D    for u in nodes:+ x$ `/ b$ y( A, m) ?3 {4 L
        distances[u][u] = 0
) r8 n% a, @/ }) r        for v, weight in graph[u].items():
. ^" [( T7 [; u6 O' {            distances[u][v] = weight
, k# o; W8 u$ o1 V6 W* ~6 R
, A+ o1 x9 v: ]  `; B    # 更新路径
/ @" x9 g6 ]7 i" C% B( N. \    for k in nodes:
3 ]2 R6 p; w% x# O6 A: u        for i in nodes:* }, w2 a% f7 Y0 q# U
            for j in nodes:: U2 A8 d4 O/ p# @4 b4 m& J
                if distances[i][j] > distances[i][k] + distances[k][j]:/ T; ^& H- I1 q9 C% B# \
                    distances[i][j] = distances[i][k] + distances[k][j]
9 N# }5 v4 [5 W% |1 E, \& L5 ~$ p& i+ Q/ B( V- l' I9 k
    return distances0 w! ~8 J8 p% \6 Z2 X& z

* z0 r, B4 A) F" X0 d" M/ X# 示例图(可以含负权边)  \: I" u, g% W+ H$ f7 T
graph_for_floyd = {4 e3 U: ^9 f# D/ z) l" H
    'A': {'B': 3, 'C': 8, 'D': -4},8 [) U: J2 l, G
    'B': {'C': 1, 'D': 7},
" C! [, z- H# n+ `. T) Z    'C': {'B': 4},  R& v- f# ^" d) q
    'D': {'A': 2, 'C': -5}
; T( |2 S# h9 j3 }- @% X' V}7 `* L' i$ q. z; r7 g9 \  i4 [; b$ u0 }
  d4 t( I+ F8 B+ g5 |- x4 H( r
shortest_paths_matrix = floyd_warshall(graph_for_floyd)  s8 l& S; \1 J: h$ }# T% c
for row in shortest_paths_matrix.items():1 R" h9 P0 C& K# ?5 D% ?5 Z8 w
    print(row)
$ ~% ^3 d, s4 n* s$ |# H3 ^- B0 b7 q```$ N: t( [; V4 ~. P, p; j" j( k

7 Y3 ~8 e8 w: y. L6 T## 总结+ f: K/ K& n6 s' ~/ k8 Y; T2 Q
* r+ ~9 s( t2 A% k" b1 w
- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。
# Q8 f9 d# ^" i$ {- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。* }9 \& ^: E3 e# X4 v7 a# D
- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。
  i) l7 p) F* ~  s; I& c! E* Y1 U- w5 W  y1 f, n- Y3 T9 q: i
不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!6 P  e* @% C  u4 I

, M% @) E" \  U6 P) d. ~6 |; _$ z* _0 ^6 l. s% ?: f
! R  b2 m! l5 K5 {0 m6 S8 ^6 o

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

回顶部