📢本篇文章是博主博主人工智能学习以及算法研究时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉强化学习专栏: 【】人工智能】- 【启发式算法】(7)---《Dijkstra算法详细介绍(Python)》
Dijkstra算法,全称迪杰斯特拉算法,是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger W. Dijkstra)在1956年提出的,是一种用于解决图中的最短路径问题的算法。这种算法适用于带权重的图,其中每条边有一个非负的权重值。
这篇论文发表于1959年的《Numerische Mathematik》期刊第1期,第269-271页,《A Note on Two Problems in Connexion with Graphs》。在这篇论文中,他不仅描述了这个算法,还提供了第一次正式的最短路径问题算法理论证明。这篇论文的题目虽然翻译成中文是《关于与图相关的两个问题的说明》,但它在算法史上有着非常重要的地位,因为其中描述的Dijkstra算法成为了解决图中最短路径问题的基石。
《A Note on Two Problems in Connexion with Graphs》的核心内容主要针对两个问题:
该论文主要介绍了两种解决图论问题的方法,分别针对构造最小生成树和寻找两点间最短路径。这两种方法在数据存储和计算工作量方面相较于其他方法具有优势,能够更高效地解决相应的问题。
《A Note on Two Problems in Connexion with Graphs》中没有直接提及“Dijkstra算法”这个名称。但其中提出的解决最短路径问题的方法后来被广泛称为Dijkstra算法。文件中针对最短路径问题所描述的解决方法,其核心思路与Dijkstra算法完全一致,即通过维护节点集合和边集合的特定方式,逐步确定从起点到其他节点的最短路径。
想象一下,你在一座迷宫里,你想要从起点A到达终点B并找到最短的路径,那么你可以使用Dijkstra算法。这个算法会帮助你计算出从起点到所有其他点的最短距离,并且最终告诉你到达终点B的最短路径是什么。
假设我们有如下的图中的四个节点和它们之间的边及其权重:
A---(2)---B
| |
(3) (1)
| |
----------------C
我们要计算从A到C的最短路径。
Dijkstra算法没有一个单一的公式,但是可以用伪代码来说明它的逻辑:
function Dijkstra(Graph, source):
dist[source] ← 0; // 初始化距离表
for each vertex v in Graph:
if v ≠ source
dist[v] ← ∞;
prev[v] ← undefined; // 前驱节点,用于记录最短路径
Q ← all vertices in Graph; // 所有顶点的集合
while Q is not empty:
u ← vertex in Q with min dist[u];
remove u from Q;
for each neighbor v of u: // 遍历u的所有邻居v
alt ← dist[u] + length(u, v);
if alt < dist[v]:
dist[v] ← alt;
prev[v] ← u;
return dist[];
这段伪代码描述了Dijkstra算法的基本流程,其中dist[]
存储从源点到各个点的距离,prev[]
用来存储最短路径树,以便最后能回溯出最短路径。
下面给出一个简单的Python实现Dijkstra算法的程序,以及一个示例图和运行结果。这个程序会计算从源点到图中所有其他节点的最短路径,并输出最短距离和路径。
"""《Dijkstra算法程序》
时间:2025.03.06
作者:不去幼儿园
"""
import heapq
def dijkstra(graph, start):
-distances = {vertex: float('infinity') for vertex in graph}
distances[start] = 0
-previous_nodes = {vertex: None for vertex in graph}
-unvisited_queue = [(0, start)]
while unvisited_queue:
current_distance, current_vertex = heapq.heappop(unvisited_queue)
if current_distance > distances[current_vertex]:
continue
for neighbor, weight in graph[current_vertex].items():
distance = current_distance + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
previous_nodes[neighbor] = current_vertex
heapq.heappush(unvisited_queue, (distance, neighbor))
return distances, previous_nodes
# Example graph represented as an adjacency list
graph = {
'A': {'B': 2, 'C': 3},
'B': {'A': 2, 'C': 1, 'D': 4},
'C': {'A': 3, 'B': 1, 'D': 5},
'D': {'B': 4, 'C': 5}
}
start_vertex = 'A'
distances, previous_nodes = dijkstra(graph, start_vertex)
# Function to print the shortest path from start_vertex to end_vertex
def print_shortest_path(previous_nodes, start_vertex, end_vertex):
path = []
current_vertex = end_vertex
while current_vertex is not None and current_vertex != start_vertex:
path.insert(0, current_vertex)
current_vertex = previous_nodes[current_vertex]
if current_vertex is None:
return "Path does not exist"
else:
path.insert(0, start_vertex)
return path
# Output the results
print("Vertex\tDistance\tPath")
for vertex in graph:
if vertex != start_vertex:
dist = distances[vertex]
path = print_shortest_path(previous_nodes, start_vertex, vertex)
print(f"{vertex}\t{dist}\t\t{path}")
上述代码中的例子图,它展示了10个节点之间的连接关系和权重。图形由顶点(A到J)和它们之间的边与权重组成:
A
/|\
B C D
/ | \
E F |
\ | /
G H
\ /
I
|
J
每个节点与其直接相连的节点都有特定的权重。下面是这些连接关系和对应的权重:
Vertex Distance Path
B 2 ->A->B
C 3 ->A->C
D 1 ->A->D
E 3 ->A->D->E
F 6 ->A->D->E->F
G 10 ->A->D->E->G
H 8 ->A->D->E->F->H
I 11 ->A->D->E->F->H->I
J 13 ->A->D->E->F->H->I->J
,其中V是顶点的数量。虽然通过使用斐波那契堆等优化措施可以将时间复杂度降低到
,但在最坏的情况下它仍然是效率较低的算法之一。