C++ 中的 Dijkstra 算法

作者:编程家 分类: c++ 时间:2025-04-15

Dijkstra算法是一种经典的图算法,用于求解带权有向图中的单源最短路径问题。该算法由荷兰计算机科学家艾兹赫尔·戴克斯特拉在1956年提出,被广泛应用于网络路由、地图导航、城市规划等领域。本文将介绍Dijkstra算法的原理和实现,并通过一个简单的案例来演示其应用。

什么是Dijkstra算法

Dijkstra算法用于求解带权有向图中一个顶点到其他所有顶点的最短路径。该算法基于贪心策略,通过逐步确定从源点到各个顶点的最短路径,并将路径长度逐步更新,直到找到所有最短路径为止。Dijkstra算法的核心思想是利用局部最优解来构造全局最优解。

算法步骤

1. 创建一个距离数组dist[],用于保存源点到各个顶点的最短距离。初始时,将源点到自身的距离设为0,其他顶点的距离设为无穷大。

2. 创建一个集合visited,用于保存已经确定最短路径的顶点。

3. 重复以下步骤,直到visited包含所有顶点:

- 从dist[]中选择一个距离最小且未被访问的顶点v,将其加入visited集合。

- 遍历顶点v的邻接顶点u,更新源点到u的距离:若dist[u] > dist[v] + weight(v, u),则更新dist[u]为dist[v] + weight(v, u),其中weight(v, u)表示边(v, u)的权重。

4. 算法结束后,dist[]中保存了源点到各个顶点的最短距离。

案例演示

下面通过一个简单的案例来演示Dijkstra算法的应用。假设有如下带权有向图:

4 2

0 ------? 1 ------? 3

| ▲

| |

|5 |3

▼ |

2 ------? 4

6

我们的目标是求解从顶点0到其他所有顶点的最短路径。

首先,初始化dist[]数组和visited集合。初始时,dist[]为[0, INF, INF, INF, INF],visited为空集。

接下来,根据算法步骤,选择距离最小且未被访问的顶点,即顶点0。将顶点0加入visited集合,并更新与其相邻顶点的距离。此时,dist[]更新为[0, 4, INF, 5, INF]。

接着,选择距离最小且未被访问的顶点,即顶点1。将顶点1加入visited集合,并更新与其相邻顶点的距离。此时,dist[]更新为[0, 4, INF, 5, 7]。

继续选择距离最小且未被访问的顶点,即顶点3。将顶点3加入visited集合,并更新与其相邻顶点的距离。此时,dist[]更新为[0, 4, INF, 5, 7],没有变化。

最后,选择距离最小且未被访问的顶点,即顶点4。将顶点4加入visited集合,并更新与其相邻顶点的距离。此时,dist[]更新为[0, 4, INF, 5, 7],没有变化。

算法结束后,dist[]中保存了从顶点0到其他所有顶点的最短距离。

代码实现

下面是使用C++实现Dijkstra算法的示例代码:

cpp

#include

#include

#include

using namespace std;

const int INF = INT_MAX;

vector dijkstra(vector>& graph, int source) {

int n = graph.size();

vector dist(n, INF);

vector visited(n, false);

dist[source] = 0;

for (int i = 0; i < n; i++) {

int u = -1;

for (int j = 0; j < n; j++) {

if (!visited[j] && (u == -1 || dist[j] < dist[u])) {

u = j;

}

}

visited[u] = true;

for (int v = 0; v < n; v++) {

if (!visited[v] && graph[u][v] != INF && dist[u] + graph[u][v] < dist[v]) {

dist[v] = dist[u] + graph[u][v];

}

}

}

return dist;

}

int main() {

vector> graph = {

{0, 4, INF, INF, 2},

{INF, 0, 2, INF, INF},

{INF, INF, 0, 3, INF},

{INF, INF, INF, 0, INF},

{INF, INF, INF, 6, 0}

};

vector shortestDist = dijkstra(graph, 0);

for (int i = 0; i < shortestDist.size(); i++) {

cout << "Shortest distance from 0 to " << i << " is " << shortestDist[i] << endl;

}

return 0;

}

以上代码使用邻接矩阵表示图,INF表示两个顶点之间不存在边。函数dijkstra()接受一个带权有向图和源点作为参数,并返回源点到各个顶点的最短距离。

在示例代码中,我们使用了一个5个顶点的图,并求解从顶点0到其他所有顶点的最短距离。最后,输出了每个顶点的最短距离。

通过这个简单的案例,我们可以看到Dijkstra算法的应用和实现过程。该算法通过不断更新距离数组来求解最短路径问题,时间复杂度为O(V^2),其中V为顶点数。在实际应用中,Dijkstra算法可以通过优先队列等数据结构进行优化,以提高算法的效率。