迪杰斯特拉算法(Dijkstra's algorithm)是一种用于在加权图中找到最短路径的算法。该算法适用于所有边权重为非负数的情况,可以处理有向图和无向图。
下面是迪杰斯特拉算法的步骤:
-
初始化:将起点的距离设置为0,将其他节点的距离设置为无穷大。将所有节点标记为未访问状态。
-
选择节点:从未访问的节点中选择距离起点最近的节点,将其标记为已访问状态。
-
更新距离:对于与当前节点相邻的节点,计算从起点到这些节点的距离,并更新它们的距离值。如果新的距离值比原来的距离值更小,则更新距离值。
-
重复步骤2和3,直到所有节点都被访问过或者目标节点被访问到。
-
回溯路径:从终点开始回溯,沿着每个节点的最短路径找到起点。
迪杰斯特拉算法的时间复杂度为O(|V|^2),其中|V|为节点数。如果使用堆优化的实现方式,时间复杂度可以降至O(|E|+|V|log|V|),其中|E|为边数。
需要注意的是,迪杰斯特拉算法只适用于边权重为非负数的情况。如果存在负权边,则需要使用其他算法,例如贝尔曼-福德算法(Bellman-Ford algorithm)或A*算法。
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
// 定义图的边
struct Edge {
int destination;
int weight;
};
// 迪杰斯特拉算法
void Dijkstra(vector<vector<Edge>>& graph, int start, vector<int>& distances) {
int n = graph.size();
vector<bool> visited(n, false);
// 初始化距离数组
distances.resize(n, INT_MAX);
distances[start] = 0;
// 优先队列,按照距离从小到大排序
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, start});
while (!pq.empty()) {
int currNode = pq.top().second;
pq.pop();
// 如果当前节点已经访问过,跳过
if (visited[currNode]) {
continue;
}
visited[currNode] = true;
for (const auto& edge : graph[currNode]) {
int nextNode = edge.destination;
int weight = edge.weight;
// 更新距离
if (!visited[nextNode] && distances[currNode] + weight < distances[nextNode]) {
distances[nextNode] = distances[currNode] + weight;
pq.push({distances[nextNode], nextNode});
}
}
}
}
int main() {
int n = 5; // 节点数
vector<vector<Edge>> graph(n);
// 添加边
graph[0].push_back({1, 10});
graph[0].push_back({4, 5});
graph[1].push_back({2, 1});
graph[1].push_back({4, 2});
graph[2].push_back({3, 4});
graph[3].push_back({2, 6});
graph[3].push_back({0, 7});
graph[4].push_back({1, 3});
graph[4].push_back({2, 9});
graph[4].push_back({3, 2});
int start = 0; // 起点
vector<int> distances;
Dijkstra(graph, start, distances);
// 输出最短路径
cout << "从起点" << start << "到其他节点的最短路径:" << endl;
for (int i = 0; i < n; ++i) {
cout << "节点 " << i << ": 距离 = " << distances[i] << endl;
}
return 0;
}
代码输出
从起点0到其他节点的最短路径:
节点 0: 距离 = 0
节点 1: 距离 = 8
节点 2: 距离 = 9
节点 3: 距离 = 7
节点 4: 距离 = 5
算法实现的总体思路,从起点开始,遍历能达到的边,记录距离,记录访问过得节点,防止重复访问;队列中保存键值对(权重-下一个节点)。
获取队列中最小的权重对应的节点,重复上一步。