@@ -128,54 +128,61 @@ for i in range(1, n + 1):
128
128
### 3.2 堆优化 Dijkstra 算法实现步骤
129
129
130
130
1 . 初始化距离数组,源点距离设为 0ドル,ドル其余节点设为无穷大。
131
- 2 . 创建优先队列,将 $(0, source)$ 入队。
131
+ 2 . 创建优先队列,将源节点及其距离 $(0, source)$ 入队。
132
132
3 . 当优先队列非空时,重复以下操作:
133
133
- 弹出队首(距离最小)节点;
134
- - 若该节点的距离已大于当前最短距离 ,跳过;
134
+ - 如果该节点的距离已大于当前最短距离 ,跳过;
135
135
- 否则,遍历其所有邻居,尝试松弛:
136
- - 若通过当前节点到邻居的距离更短 ,则更新距离并将新距离入队。
136
+ - 如果通过当前节点到邻居的距离更短 ,则更新距离并将新距离入队。
137
137
4 . 队列为空时结束,返回所有节点的最短距离数组。
138
138
139
- ### 3.3 堆优化的 Dijkstra 算法实现代码
139
+ ### 3.3 堆优化 Dijkstra 算法实现代码
140
140
141
141
``` python
142
142
import heapq
143
143
144
144
class Solution :
145
145
def dijkstra (self , graph , n , source ):
146
- # 初始化距离数组
147
- dist = [float (' inf' ) for _ in range (n + 1 )]
148
- dist[source] = 0
149
-
150
- # 创建优先队列,存储 (距离, 节点) 的元组
146
+ """
147
+ 堆优化 Dijkstra 算法,计算单源最短路径
148
+ :param graph: 邻接表,graph[u] = {v: w, ...}
149
+ :param n: 节点总数(节点编号从 1 到 n)
150
+ :param source: 源点编号
151
+ :return: dist[i] 表示源点到 i 的最短距离
152
+ """
153
+ # 距离数组,初始化为无穷大
154
+ dist = [float (' inf' )] * (n + 1 )
155
+ dist[source] = 0 # 源点到自身距离为 0
156
+
157
+ # 小根堆,存储 (距离, 节点) 元组
151
158
priority_queue = [(0 , source)]
152
-
159
+
153
160
while priority_queue:
154
161
current_distance, current_node = heapq.heappop(priority_queue)
155
-
156
- # 如果当前距离大于已知的最短距离,跳过
162
+ # 如果弹出的节点距离不是最短的,说明已被更新,跳过
157
163
if current_distance > dist[current_node]:
158
164
continue
159
-
160
- # 遍历当前节点的所有相邻节点
161
- for neighbor, weight in graph[current_node].items():
162
- distance = current_distance + weight
163
- if distance < dist[neighbor]:
164
- dist[neighbor] = distance
165
- heapq.heappush(priority_queue, (distance, neighbor))
166
-
165
+
166
+ # 遍历当前节点的所有邻居
167
+ for neighbor, weight in graph.get(current_node, {}).items():
168
+ new_distance = current_distance + weight
169
+ # 如果找到更短路径,则更新并入堆
170
+ if new_distance < dist[neighbor]:
171
+ dist[neighbor] = new_distance
172
+ heapq.heappush(priority_queue, (new_distance, neighbor))
173
+
167
174
return dist
168
175
169
176
# 使用示例
170
- # 创建一个有向图,使用邻接表表示
177
+ # 构建一个有向图,邻接表表示
171
178
graph = {
172
179
1 : {2 : 2 , 3 : 4 },
173
180
2 : {3 : 1 , 4 : 7 },
174
181
3 : {4 : 3 },
175
182
4 : {}
176
183
}
177
- n = 4 # 图中节点数量
178
- source = 1 # 源节点
184
+ n = 4 # 节点数量
185
+ source = 1 # 源点编号
179
186
180
187
dist = Solution().dijkstra(graph, n, source)
181
188
print (" 从节点" , source, " 到其他节点的最短距离:" )
@@ -186,27 +193,15 @@ for i in range(1, n + 1):
186
193
print (f " 到节点 { i} 的距离: { dist[i]} " )
187
194
```
188
195
189
- 代码解释:
190
-
191
- 1 . ` graph ` 是一个字典,表示图的邻接表。例如,` graph[1] = {2: 3, 3: 4} ` 表示从节点 1 到节点 2 的边权重为 3,到节点 3 的边权重为 4。
192
- 2 . ` n ` 是图中顶点的数量。
193
- 3 . ` source ` 是源节点的编号。
194
- 4 . ` dist ` 数组存储源点到各个节点的最短距离。
195
- 5 . ` priority_queue ` 是一个优先队列,用来选择当前距离源点最近的节点。队列中的元素是 (距离, 节点) 的元组。
196
- 6 . 主循环中,每次从队列中取出距离最小的节点。如果该节点的距离已经被更新过,跳过。
197
- 7 . 对于当前节点的每一个邻居,计算通过当前节点到达邻居的距离。如果这个距离比已知的更短,更新距离并将邻居加入队列。
198
- 8 . 最终,` dist ` 数组中存储的就是源点到所有节点的最短距离。
199
-
200
- ### 3.4 堆优化的 Dijkstra 算法复杂度分析
196
+ ### 3.4 堆优化 Dijkstra 算法复杂度分析
201
197
202
- - ** 时间复杂度** :$O((V + E) \log V)$
203
- - 每个节点最多被加入优先队列一次,每次操作的时间复杂度为 $O(\log V)$
204
- - 每条边最多被处理一次,每次处理的时间复杂度为 $O(\log V)$
205
- - 因此总时间复杂度为 $O((V + E) \log V)$
198
+ - ** 时间复杂度** :$O((V + E) \log V)$。
199
+ - 堆优化 Dijkstra 算法中,每个节点最多会被弹出优先队列一次,每次弹出操作的复杂度为 $O(\log V)$。
200
+ - 每条边在松弛操作时最多会导致一次入堆,入堆操作的复杂度同样为 $O(\log V)$。
201
+ - 因此,总体时间复杂度为 $O((V + E) \log V)$,其中 $V$ 为节点数,$E$ 为边数。
206
202
207
- - ** 空间复杂度** :$O(V)$
208
- - 需要存储距离数组,大小为 $O(V)$。
209
- - 优先队列在最坏情况下可能存储所有节点,大小为 $O(V)$。
203
+ - ** 空间复杂度** :$O(V)$。
204
+ - 主要空间消耗在距离数组和优先队列,二者最坏情况下均为 $O(V)$ 级别。
210
205
211
206
## 练习题目
212
207
0 commit comments