在无权图中,单源最短路径问题通常可以通过广度优先搜索(BFS)算法来解决。BFS是一种基于队列的图遍历算法,它从源点开始,逐层扩展,直到找到目标节点或遍历完所有节点。由于无权图中所有边的权重相同,BFS能够保证找到的路径是最短的。
BFS算法的时间复杂度为O(V+E),其中V是图中顶点的数量,E是边的数量。由于BFS访问每个顶点和边的次数最多为一次,因此在无权图中效率较高。
BFS算法步骤:
- 初始化:创建一个队列,将源点入队,同时标记源点为已访问
- 层序遍历:从队列中取出一个节点,访问它的所有未访问的邻居节点。如果邻居节点未被访问过,则将其标记为已访问,并将其加入队列
- 重复:重复步骤2,直到队列为空或找到目标节点
- 路径重建:通过记录每个节点的前驱节点,可以从目标节点回溯到源节点,重建最短路径
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
const int MAX_VERTICES = 100; // 假设图中最多有100个顶点
const int INF = INT_MAX; // 用INT_MAX表示无穷大,即不可达的状态
// 邻接表表示的无权图
class UnweightedGraph {
private:
int vertex_number; // 顶点的数量
std::vector<std::vector<int>> adjacency_table; // 邻接表
public:
// 构造函数,并将参数赋值给私有成员变量
UnweightedGraph(int val) : vertex_number(val), adjacency_table(val) {
// 判断传入的顶点数是否超过最大顶点数
if (val > MAX_VERTICES) {
std::cout << "传入的顶点数已超过可接纳的最大顶点数,将导致程序终止!" << std::endl;
std::exit(EXIT_SUCCESS); // 终止程序
}
// 查看邻接表的初始值,并无实际意义,可注释掉
for (int i = 0; i < adjacency_table.size(); ++i) {
for (auto value : adjacency_table[i]) {
std::cout << value << " ";
}
std::cout << std::endl;
}
}
// 添加有向边,参数传入两个顶点,顶点v指向顶点w
void add_edge(int v, int w) {
adjacency_table[v].push_back(w);
}
// BFS算法实现
void bfs(int src) {
std::queue<int> q; // 创建队列
std::vector<int> dist(vertex_number, INF); // 存储从源点到每个顶点的距离
std::vector<bool> visited(vertex_number, false); // 标记顶点是否已访问
// 初始化源点
dist[src] = 0;
// 将源点加入队列,并标记为已访问
q.push(src);
visited[src] = true;
while (!q.empty()) {
// 取出队首元素
int v = q.front();
q.pop();
// 遍历所有邻接顶点
for (int neighbor : adjacency_table[v]) {
if (!visited[neighbor]) {
dist[neighbor] = dist[v] + 1; // 更新距离
q.push(neighbor);
visited[neighbor] = true;
}
}
}
// 输出结果
for (int i = 0; i < vertex_number; i++) {
if (dist[i] == INF)
std::cout << "Vertex v" << i+1 << " is not reachable from source\n";
else
std::cout << "Shortest path to vertex v" << i+1 << " is " << dist[i] << " edges away\n";
}
}
};
int main() {
UnweightedGraph g(8); // 实例化类对象
// 构建有向无权图
g.add_edge(0, 1);
g.add_edge(0, 3);
g.add_edge(1, 3);
g.add_edge(1, 4);
g.add_edge(2, 0);
g.add_edge(2, 5);
g.add_edge(3, 2);
g.add_edge(3, 4);
g.add_edge(3, 5);
g.add_edge(3, 6);
g.add_edge(4, 6);
g.add_edge(6, 5);
std::cout << "Shortest paths from source vertex v3:\n";
g.bfs(2); // 调用bfs算法
return 0;
}
---------
Shortest paths from source vertex v3:
Shortest path to vertex v1 is 1 edges away
Shortest path to vertex v2 is 2 edges away
Shortest path to vertex v3 is 0 edges away
Shortest path to vertex v4 is 2 edges away
Shortest path to vertex v5 is 3 edges away
Shortest path to vertex v6 is 1 edges away
Shortest path to vertex v7 is 3 edges away
Vertex v8 is not reachable from source