单源最短路径(Single Source Shortest Path):对于一个带权图 $G = (V, E)$,其中每条边的权重是一个实数。另外,给定 $v$ 中的一个顶点,称之为源点。则源点到其他所有各个顶点之间的最短路径长度,称为单源最短路径。
这里的路径长度,指的是路径上各边权之和。
单源最短路径问题的核心是找到从源点到其他各个顶点的路径,使得路径上边的权重之和最小。这个问题在许多实际应用中都非常重要,比如网络路由、地图导航、通信网络优化等。
常见的解决单源最短路径问题的算法包括:
这些算法根据图的特点和问题的需求有所不同,选择适合的算法可以在不同情况下有效地解决单源最短路径问题。
Dijkstra 算法的算法思想:通过逐步选择距离起始节点最近的节点,并根据这些节点的路径更新其他节点的距离,从而逐步找到最短路径。
Dijkstra 算法是一种用来解决单源最短路径问题的算法。这个算法适用于没有负权边的图。算法的核心思想是从源点出发,逐步找到到其他所有点的最短路径。它通过不断选择当前距离源点最近的节点,并更新与该节点相邻的节点的距离,最终得到所有节点的最短路径。
Dijkstra 算法使用贪心的策略。它每次选择当前未处理的节点中距离源点最近的节点,认为这个节点的最短路径已经确定。然后,它用这个节点的最短路径去更新其他相邻节点的距离。这个过程重复进行,直到所有节点的最短路径都被确定。
Dijkstra 算法的一个重要特点是它不能处理有负权边的图。因为负权边可能导致已经确定的最短路径被破坏。如果图中存在负权边,应该使用 Bellman-Ford 算法或 SPFA 算法。
class Solution:
def dijkstra(self, graph, n, source):
# 初始化距离数组
dist = [float('inf') for _ in range(n + 1)]
dist[source] = 0
# 记录已处理的节点
visited = set()
while len(visited) < n:
# 选择当前未处理的、距离源点最近的节点
current_node = None
min_distance = float('inf')
for i in range(1, n + 1):
if i not in visited and dist[i] < min_distance:
min_distance = dist[i]
current_node = i
# 如果没有可处理的节点(非连通图),提前结束
if current_node is None:
break
# 标记当前节点为已处理
visited.add(current_node)
# 更新相邻节点的距离
for neighbor, weight in graph[current_node].items():
new_distance = dist[current_node] + weight
if new_distance < dist[neighbor]:
dist[neighbor] = new_distance
return dist
# 使用示例
# 创建一个有向图,使用邻接表表示
graph = {
1: {2: 2, 3: 4},
2: {3: 1, 4: 7},
3: {4: 3},
4: {}
}
n = 4 # 图中节点数量
source = 1 # 源节点
dist = Solution().dijkstra(graph, n, source)
print("从节点", source, "到其他节点的最短距离:")
for i in range(1, n + 1):
if dist[i] == float('inf'):
print(f"到节点 {i} 的距离:不可达")
else:
print(f"到节点 {i} 的距离:{dist[i]}")
时间复杂度:$O(V^2)$
空间复杂度:$O(V)$
dist
,大小为 $O(V)$visited
,大小为 $O(V)$堆优化的 Dijkstra 算法:通过使用优先队列(堆)来优化选择最小距离节点的过程,从而降低算法的时间复杂度。
在原始的 Dijkstra 算法中,每次都需要遍历所有未访问的节点来找到距离最小的节点,这个过程的时间复杂度是 $O(V)$。通过使用优先队列(堆)来维护当前已知的最短距离,我们可以将这个过程的时间复杂度优化到 $O(\log V)$。
堆优化的主要思想是:
import heapq
class Solution:
def dijkstra(self, graph, n, source):
# 初始化距离数组
dist = [float('inf') for _ in range(n + 1)]
dist[source] = 0
# 创建优先队列,存储 (距离, 节点) 的元组
priority_queue = [(0, source)]
while priority_queue:
current_distance, current_node = heapq.heappop(priority_queue)
# 如果当前距离大于已知的最短距离,跳过
if current_distance > dist[current_node]:
continue
# 遍历当前节点的所有相邻节点
for neighbor, weight in graph[current_node].items():
distance = current_distance + weight
if distance < dist[neighbor]:
dist[neighbor] = distance
heapq.heappush(priority_queue, (distance, neighbor))
return dist
# 使用示例
# 创建一个有向图,使用邻接表表示
graph = {
1: {2: 2, 3: 4},
2: {3: 1, 4: 7},
3: {4: 3},
4: {}
}
n = 4 # 图中节点数量
source = 1 # 源节点
dist = Solution().dijkstra(graph, n, source)
print("从节点", source, "到其他节点的最短距离:")
for i in range(1, n + 1):
if dist[i] == float('inf'):
print(f"到节点 {i} 的距离:不可达")
else:
print(f"到节点 {i} 的距离:{dist[i]}")
代码解释:
graph
是一个字典,表示图的邻接表。例如,graph[1] = {2: 3, 3: 4}
表示从节点 1 到节点 2 的边权重为 3,到节点 3 的边权重为 4。n
是图中顶点的数量。source
是源节点的编号。dist
数组存储源点到各个节点的最短距离。priority_queue
是一个优先队列,用来选择当前距离源点最近的节点。队列中的元素是 (距离, 节点) 的元组。dist
数组中存储的就是源点到所有节点的最短距离。时间复杂度:$O((V + E) \log V)$
空间复杂度:$O(V)$
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。