C++ 语言 实现图算法最短路径

C++阿木 发布于 3 天前 3 次阅读


阿木博主一句话概括:C++实现图算法之最短路径问题

阿木博主为你简单介绍:最短路径问题是图论中的一个经典问题,广泛应用于网络通信、路径规划等领域。本文将围绕C++语言,介绍几种常见的图算法,包括Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法,并给出相应的C++实现代码。

一、

最短路径问题是指在一个加权图中,寻找两个顶点之间的最短路径。在现实世界中,如地图导航、物流配送等场景,都需要解决最短路径问题。本文将介绍三种常用的图算法,并给出C++实现代码。

二、Dijkstra算法

Dijkstra算法是一种基于贪心策略的单源最短路径算法,适用于无负权边的图。其基本思想是:从源点开始,逐步扩展到相邻的顶点,每次选择距离源点最近的顶点,直到所有顶点都被访问过。

1. 算法步骤

(1)初始化:将源点加入集合S,其余顶点加入集合U;将所有顶点的距离初始化为无穷大,源点的距离为0。

(2)选择集合U中距离源点最近的顶点v,将其加入集合S。

(3)对于集合U中的每个顶点w,如果w是v的邻接顶点,则更新w的距离:distance[w] = min(distance[w], distance[v] + weight(v, w))。

(4)重复步骤(2)和(3),直到集合U为空。

2. C++实现

cpp
include
include
include
include

using namespace std;

const int MAX_VERTICES = 100;
int graph[MAX_VERTICES][MAX_VERTICES];
int distance[MAX_VERTICES];
bool visited[MAX_VERTICES];

void dijkstra(int source) {
priority_queue<#pair, vector<#pair>, greater<#pair>> pq;
pq.push(make_pair(0, source));
distance[source] = 0;

while (!pq.empty()) {
int u = pq.top().second;
pq.pop();

if (visited[u]) continue;
visited[u] = true;

for (int v = 0; v < MAX_VERTICES; ++v) {
if (graph[u][v] && !visited[v]) {
int alt = distance[u] + graph[u][v];
if (alt < distance[v]) {
distance[v] = alt;
pq.push(make_pair(distance[v], v));
}
}
}
}
}

int main() {
// 初始化图
// ...

// 调用Dijkstra算法
dijkstra(0);

// 输出最短路径
// ...

return 0;
}

三、Bellman-Ford算法

Bellman-Ford算法是一种适用于有负权边的图的单源最短路径算法。其基本思想是:从源点开始,逐步扩展到相邻的顶点,每次选择距离源点最近的顶点,直到所有顶点都被访问过。

1. 算法步骤

(1)初始化:将源点加入集合S,其余顶点加入集合U;将所有顶点的距离初始化为无穷大,源点的距离为0。

(2)对于每个顶点,执行以下操作n-1次(n为顶点数):

a. 对于集合U中的每个顶点v,如果v是u的邻接顶点,则更新v的距离:distance[v] = min(distance[v], distance[u] + weight(u, v))。

b. 如果某个顶点的距离在本次迭代中发生了变化,则将这个顶点加入集合U。

(3)检查是否有负权环:对于所有边(u, v),如果distance[v] > distance[u] + weight(u, v),则存在负权环。

2. C++实现

cpp
include
include
include

using namespace std;

const int MAX_VERTICES = 100;
int graph[MAX_VERTICES][MAX_VERTICES];
int distance[MAX_VERTICES];

void bellmanFord(int source) {
for (int i = 0; i < MAX_VERTICES - 1; ++i) {
for (int u = 0; u < MAX_VERTICES; ++u) {
for (int v = 0; v < MAX_VERTICES; ++v) {
if (graph[u][v] && distance[u] != INT_MAX && distance[u] + graph[u][v] < distance[v]) {
distance[v] = distance[u] + graph[u][v];
}
}
}
}

// 检查负权环
for (int u = 0; u < MAX_VERTICES; ++u) {
for (int v = 0; v < MAX_VERTICES; ++v) {
if (graph[u][v] && distance[u] != INT_MAX && distance[u] + graph[u][v] < distance[v]) {
cout << "Graph contains negative weight cycle" << endl;
return;
}
}
}
}

int main() {
// 初始化图
// ...

// 调用Bellman-Ford算法
bellmanFord(0);

// 输出最短路径
// ...

return 0;
}

四、Floyd-Warshall算法

Floyd-Warshall算法是一种适用于所有加权图的算法,可以找到任意两个顶点之间的最短路径。其基本思想是:逐步考虑所有可能的中间顶点,逐步更新顶点对之间的最短路径。

1. 算法步骤

(1)初始化:将所有顶点的距离初始化为无穷大,对角线上的距离初始化为0。

(2)对于每个顶点k,执行以下操作:

a. 对于所有顶点i,如果distance[i][k] + distance[k][j] < distance[i][j],则更新distance[i][j]。

2. C++实现

cpp
include
include
include

using namespace std;

const int MAX_VERTICES = 100;
int graph[MAX_VERTICES][MAX_VERTICES];
int distance[MAX_VERTICES][MAX_VERTICES];

void floydWarshall() {
for (int k = 0; k < MAX_VERTICES; ++k) {
for (int i = 0; i < MAX_VERTICES; ++i) {
for (int j = 0; j < MAX_VERTICES; ++j) {
if (graph[i][k] && graph[k][j] && distance[i][k] + distance[k][j] < distance[i][j]) {
distance[i][j] = distance[i][k] + distance[k][j];
}
}
}
}
}

int main() {
// 初始化图
// ...

// 调用Floyd-Warshall算法
floydWarshall();

// 输出最短路径
// ...

return 0;
}

五、总结

本文介绍了三种常见的图算法:Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法,并给出了相应的C++实现代码。这些算法在解决最短路径问题时具有不同的适用场景,读者可以根据实际需求选择合适的算法。在实际应用中,可以根据具体问题对算法进行优化和改进,以提高算法的效率和准确性。