Dijkstra算法是一种用于解决单源最短路径问题的经典算法,用于计算图中从一个源节点到所有其他节点的最短路径。该算法最初由荷兰计算机科学家艾兹赫·迪克斯特拉于1956年提出。
以下是Dijkstra算法的详细介绍:
算法步骤:
-
初始化:创建一个距离数组
dist[]
,该数组存储从源节点到每个节点的当前最短距禿估计值。距离数组初始化为无穷大,源节点的距离设为0。创建一个集合S
,用于存储已经找到最短路径的节点,初始时S
为空。 -
迭代更新:重复以下步骤,直到找到所有节点的最短路径或者集合
S
包含了所有节点:- 从距离数组
dist[]
中选择当前距离最小的节点u
,并将其加入S
中。 - 对于节点
u
的每个邻居节点v
,更新v
的最短距离估计值:- 计算从源节点经过节点
u
到节点v
的距离alt
,即dist[u] + weight(u, v)
,其中weight(u, v)
表示从节点u
到节点v
的边的权重。 - 如果
alt
小于dist[v]
,则更新dist[v]
的值为alt
。
- 计算从源节点经过节点
- 从距离数组
-
输出结果:当算法结束时,距离数组
dist[]
中存储的就是从源节点到每个节点的最短距离。
示例:
假设有如下图示的带权重的有向图:
10
(A) --------► (B)
| ▲
| |
| | 5
| |
| |
►--------► (C)
1
从节点A到其他节点的边的权重分别为:AB=10, AC=1, BC=5。
通过Dijkstra算法,我们可以计算出从节点A到其他节点的最短路径距离:
- 节点A到节点A的最短路径距离为0(初始值)。
- 节点A到节点B的最短路径距离为6(经过节点C)。
- 节点A到节点C的最短路径距离为1。
复杂度:
Dijkstra算法的时间复杂度取决于选择最小距离节点的方法。使用最小堆数据结构可以将算法的时间复杂度优化到O((V + E)logV),其中V为节点数量,E为边的数量。
实现:
以下是一个简单的C++实现示例,使用了STL中的优先队列(最小堆)来优化算法的时间复杂度:
#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <climits>
#define INF INT_MAX
using namespace std;
void dijkstra(vector<vector<pair<int, int>>> &graph, int source) {
int n = graph.size();
vector<int> dist(n, INF);
dist[source] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, source});
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
for (auto &[v, weight] : graph[u]) {
if (dist[u] != INF && dist[v] > dist[u] + weight) {
dist[v] = dist[u] + weight;
pq.push({dist[v], v});
}
}
}
for (int i = 0; i < n; ++i) {
cout << "Distance from " << source << " to " << i << " is " << dist[i] << endl;
}
}
int main() {
int n = 3; // 节点数量
vector<vector<pair<int, int>>> graph(n);
graph[0].push_back({1, 10});
graph[0].push_back({2, 1});
graph[1].push_back({2, 5});
dijkstra(graph, 0); // 从节点0开始计算最短路径
return 0;
}
希望这个简单的介绍能帮助你理解Dijkstra算法的基本原理和实现方式。如果有其他问题,欢迎在评论区留言!