QQ登录

只需要一步,快速开始

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

最短路径算法Python代码

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

1189

主题

4

听众

2934

积分

该用户从未签到

跳转到指定楼层
1#
发表于 2025-1-13 17:26 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
最短路径算法用于寻找图中两点之间的最短路径。这类算法在网络路由、地图导航、物流和许多其他应用中起到关键作用。常见的最短路径算法包括 Dijkstra 算法、Bellman-Ford 算法和 Floyd-Warshall 算法。下面将介绍这些算法的基本原理和具体实现。
- h6 C3 y% F& o7 w& c2 \
; e) ~' e. f% B* }## 1. Dijkstra 算法+ N+ \+ w) Q1 k
4 R3 f1 y4 w* B  f
Dijkstra 算法用于计算单源最短路径,有效于边权为非负数的图。它通过贪心策略逐步选择最短路径,从起点出发扩展到其他节点。
# G: n* G0 f# `7 k# w, `& R9 {5 {5 Q' I( t& {; w& s( d
### 原理步骤
8 o4 e9 G$ a. Y- t  D; _9 ]
% `& H0 k4 M" {! S3 I+ X3 |1. **初始化**:
7 `" V0 `) T. `   - 设置源节点到自己的距离为0,其他节点为无穷大(一般用 `inf` 表示)。
1 I0 v$ d& t) ~0 }/ r   - 初始化一个空的优先队列,用于存储待处理的节点。
4 S2 h9 O6 R/ {$ d1 B" w! w/ U8 K1 q0 g1 x+ S- m8 ]# Y$ r: k, i
2. **处理节点**:8 J2 ]/ U3 l  W4 N: u( k8 [$ g. k
   - 从优先队列中选取距离最小的节点作为当前节点。
; c, Z" M3 f1 M( y7 l* n   - 更新当前节点的所有邻接节点的距离。如果新的距离更短,则更新并将邻接节点加入优先队列。
& u3 I0 b0 g/ D/ q
4 k0 @. |6 T# p  h3 m" Z: J; \/ o9 M3. **重复处理**:& D- ?2 M" e+ D& T: L: j- ?; D
   - 继续选择距离最小的节点,直到处理完所有节点或找到目标节点。
9 _& g  B* U1 ?& y0 K9 ~$ |. e7 W: }: `; ^3 E
### 示例代码
) o* }8 X; f! d* U' s" P: C7 j3 R
```python( d% j: B' m" z. C7 a2 \2 z2 B
import heapq7 g" b: E/ ]+ L0 Q& S& T5 P

3 B, g6 j8 d3 u6 {9 Q# J. Gdef dijkstra(graph, start):( R* j9 \. Y, m$ h
    # 图的表示为字典,键为节点,值为邻接节点及其边权2 l' d& K9 T7 _; ]; a
    queue = []+ N) n+ u5 x. |& o
    distances = {node: float('inf') for node in graph}
" {; e; C+ q3 q! @# b    distances[start] = 0
3 ^8 o) d3 u2 }5 Y' J9 Z8 ^    heapq.heappush(queue, (0, start))  # (距离, 节点); D3 u* l' B$ }# C* D" ]4 z
! J) a6 U- f$ i; U3 W7 R
    while queue:* P* ^" _2 i2 ]
        current_distance, current_node = heapq.heappop(queue)8 I8 F2 g1 S' s& R
* o3 X& R+ b4 r0 e
        # 只处理当前节点的最短距离
5 l) q2 B/ ~! l4 m, K        if current_distance > distances[current_node]:
  R0 H/ t  S3 ~* l3 w" D            continue
% \* s2 D! j, v; B4 i! y
$ l. F) x/ p% ~( R( @, t( [        for neighbor, weight in graph[current_node].items():
$ t# I4 X* e, L* Y            distance = current_distance + weight0 `% O+ G2 J1 g" \' {

& n8 Z) ~' j* }* u            # 更新邻接节点的距离
! Q) @5 A4 O& c" D) K            if distance < distances[neighbor]:
, Y+ ~7 O$ S# J# Y6 u. r) Z% E                distances[neighbor] = distance1 Z+ J& g3 r6 C2 A1 @
                heapq.heappush(queue, (distance, neighbor))
: Y" y& ~8 G" }) r; z* Y9 J; c  v/ _$ a7 n& d- J
    return distances
# W0 b; A& F5 D3 F# l, n$ n2 Q7 c& o& Y
# 示例图: L: v6 e8 b/ ?! ?
graph = {
2 Z1 G; q* c5 f) [+ p5 {    'A': {'B': 1, 'C': 4},
8 n8 \& Z0 D5 _! |- l& I! Q    'B': {'A': 1, 'C': 2, 'D': 5},
" Z% ?1 `* T' U5 {/ P2 F# q    'C': {'A': 4, 'B': 2, 'D': 1},
9 p  G: A+ }2 ]    'D': {'B': 5, 'C': 1},9 w" q; d/ U7 x7 s, C8 ?1 k
}, p; Q. f/ S1 P! T! i% j3 O

/ x4 s8 M) c  V; W: m3 y% mstart_node = 'A'( P5 k; ]" o1 h) c: _
shortest_paths = dijkstra(graph, start_node)
4 R& A0 X/ W3 N3 }# O8 w# Bprint(shortest_paths)  # {'A': 0, 'B': 1, 'C': 3, 'D': 4}' U0 V0 J7 O- M. I9 E- q
```
7 ?% O  B8 Q4 ]/ y
  r4 L" i3 a$ m2 A, K## 2. Bellman-Ford 算法/ j: `0 g9 {/ Y& F. G

7 B7 g  [8 U; T0 lBellman-Ford 算法能够处理带有负权边的图,但不能处理负权回路。它通过放松操作逐步更新从源节点到所有其他节点的最短路径。
0 H- P$ Q7 M, m# N
- J, F% ~0 ]7 @  F5 ?0 E### 原理步骤
0 B" G8 z3 w7 `) T8 P
# B0 _! N+ I7 k. P7 A. p1. **初始化**:
% ]  \* j7 i& n# e   - 设置源节点到自己的距离为0,其他节点为无穷大。
; Q8 ^7 E) ?! y& T' x4 V1 n: m( d. Q* B
2. **松弛操作**:
7 E9 X$ u" u- u) z, U   - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。7 x. @$ C/ U6 l; c# G8 e; u
+ G) A, c8 }" ]  u3 m0 c& @
3. **检查负权回路**:! w: z( ~# s" p5 Y; }" A
   - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。
8 e0 j3 M' P( x% K6 V) z# @3 _7 ^- r5 d; U9 f4 T( l" }# ?6 A
### 示例代码
. Y5 b  o, J- r2 p) B4 s7 w' u& `* \. s+ ^; A; x3 b7 @
```python2 A# _3 j8 N$ p9 P9 N
def bellman_ford(graph, start):9 X' n& d+ {8 u+ T  g
    # 初始化距离
3 W0 K# s' w  J# N  ], y6 v    distances = {node: float('inf') for node in graph}6 T# D+ N4 d9 H" l5 E
    distances[start] = 0
) K8 A2 Y+ Z# S3 J9 Y; N& W/ q
! [3 k8 y) y% P+ E2 x9 y4 T9 I+ k6 `    # 松弛操作
" i. f& Y; `$ v& P2 }3 u+ e    for _ in range(len(graph) - 1):# M+ Q& L4 I6 V! `5 Q+ Y0 p
        for u in graph:: v$ _/ f/ k  ^7 b( b9 D) `
            for v, weight in graph[u].items():
+ b* w- @; c6 R; k) M  _, Z                if distances[u] + weight < distances[v]:! [4 N9 h* T7 K) Y! G( O
                    distances[v] = distances[u] + weight- {) F# F6 G9 S. w6 J7 h4 m8 u, c

6 a: Z% N. A3 j1 {3 ~7 R7 r5 x2 I    # 检查负权回路2 \1 M( D* a1 m  ~% _8 p/ }# V
    for u in graph:
+ {5 d. r0 `9 s' V1 y        for v, weight in graph[u].items():
9 T+ p6 S' f4 j4 T" e5 f' Z& E! n$ h            if distances[u] + weight < distances[v]:* M& a4 J0 C; s3 i  \( p$ O1 n
                raise ValueError("Graph contains a negative weight cycle")  Y# I# o( n- M' g+ V) n  x- R0 a

7 l. C7 r" V7 e* U    return distances
& O7 H: ^4 Y! ?0 b
* y& S8 i- ?, _; A9 C# 示例图(带有负权边)
$ T5 ?4 s  N2 e7 `+ A5 v% ~& e0 ~graph_with_negative_weight = {
$ R# E1 M5 c5 ]% u" |8 c! x) ^1 V6 L$ s    'A': {'B': 1, 'C': 4},
7 z0 ^- `* e3 g0 ^* |+ v& i; J    'B': {'C': -3, 'D': 2},( \/ h, P% \! |" j# f
    'C': {},
6 ?& G' h* B. ~7 X: D& ?7 H/ V+ u    'D': {'A': -1}7 S' w) u9 Q4 c# ~' v
}- c' l9 n: ~  w* F  G% a

$ D, f' v1 |4 C9 x+ M" t" L! Kstart_node = 'A'+ P$ `0 W" z% C7 A: `( G1 q7 g, _
shortest_paths = bellman_ford(graph_with_negative_weight, start_node)( v! S5 f; }; t# ^! m. A5 g8 H( |
print(shortest_paths)  # {'A': 0, 'B': 1, 'C': -2, 'D': 3}1 I# z3 M) F4 |# b. C: G
```6 `  ?  z; f- T+ @& T

1 T. ~5 ^. I( T8 Q/ }## 3. Floyd-Warshall 算法& h' f4 ^- ]7 T+ K

, P, d3 {& y/ R) {* JFloyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。4 l6 {0 l: j5 G4 {
0 e# `" D8 w, m3 b/ o8 x# s- y
### 原理步骤8 Y: v" U5 @6 c3 U) m7 f( L$ n0 F

& P5 t9 N* d  J" H9 |1. **初始化**:- s% y8 f8 j* X; H: _/ L2 ~
   - 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。
# b- N7 @' u7 B! d( k7 f  p5 e( D, K8 q; g, @) W3 F; R+ C
2. **更新路径**:! f3 ]& _6 k1 a- ?7 W7 E
   - 三重循环遍历所有节点,以每个中间节点尝试更新路径。$ V. T" z8 T0 M* j# _; T  w* m' x

0 t" Y4 z" L) g! R/ `( @, F3. **输出结果**:
1 X8 w) K) q9 }% S1 q   - 最终得到的矩阵即为每对节点之间的最短路径长度。% K9 @  C" _1 @
) R2 Z7 \* v+ b0 B5 t# M/ e- G
### 示例代码
" N7 @  e. w. F( A' h" a9 h
  t; U0 L. U% T1 i```python
( E! R: ?8 k! }, ]% jdef floyd_warshall(graph):
  s* [# h$ c, I3 ?, Y, t' o; v% ^. k    # 初始化距离矩阵" p  m" }2 u& E% M/ Q2 z" b
    nodes = list(graph.keys())6 K5 j* o- n. ?. h
    distances = {node: {n: float('inf') for n in nodes} for node in nodes}
& d/ _, F) t) i* V# V1 v* O5 ~% U& U2 E# d6 v
    for u in nodes:
. S9 J; j. [0 y' t( P' Z        distances[u][u] = 0
) l3 e0 I! s2 v        for v, weight in graph[u].items():* \& f: ~' z9 o
            distances[u][v] = weight
  ~* |$ {( h1 A) O2 v0 x
, f1 B8 B; J3 b* d, Y7 i  K1 Y    # 更新路径% \) L  V9 v* R0 K
    for k in nodes:. i5 c: i) ?# F% i# H) N
        for i in nodes:( _* F+ c- ?0 P0 a
            for j in nodes:1 j) p9 X$ m4 z0 A9 i; U; e! M6 H
                if distances[i][j] > distances[i][k] + distances[k][j]:: ?  f' p  Z8 ^3 W/ l; n
                    distances[i][j] = distances[i][k] + distances[k][j]
4 p- g" x" Z; h+ l0 Y
- f" v" W3 o3 W& Z1 G/ {% J+ j    return distances. z. _: Q: v7 z6 O$ j' E

8 Y6 T' w4 u3 ?5 u9 V3 |5 X. _# 示例图(可以含负权边)( z2 ]( E$ v" \, s
graph_for_floyd = {
9 ]9 N% x1 N% H9 V2 k    'A': {'B': 3, 'C': 8, 'D': -4},) @9 D4 N: T4 G$ R% S' l) a+ o
    'B': {'C': 1, 'D': 7},' k9 a7 j; o0 |' W% W# m1 ]
    'C': {'B': 4},
  k5 w+ Y& o1 ]2 |2 r( @    'D': {'A': 2, 'C': -5}, ~, |" B0 y- r, y# C9 v& |+ l4 j: ]
}& P+ M. n! U' H" P, N$ K. b: _

) n# f1 [9 O: B2 h& X! q- S$ sshortest_paths_matrix = floyd_warshall(graph_for_floyd)! k* n! X4 M$ q1 g) b) _4 _  d
for row in shortest_paths_matrix.items():
* k; r5 g* i: E    print(row)1 t) D& ^4 a: n' F: J
```
" V5 Q6 H3 v: P# H) d; T% U5 G% {( F! N+ p3 K, |: S' E' w
## 总结" B3 l8 @0 r6 n/ [8 p

( @$ E) J9 `; v- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。5 X5 T# A9 p5 `$ l, z
- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。
, T8 h$ I/ E6 {# q) W- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。
: Q' X; z5 Z- g2 M- U) }8 |3 q$ u9 q5 N& r" N
不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!- F# K% i; B7 H, C) `

. O' q# A- \6 G  i: A# o% P) F! B0 g9 \% |0 k/ @
9 K( j( [! c4 _2 H: e- t% 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-7-9 21:50 , Processed in 0.454630 second(s), 55 queries .

回顶部