BFS和贝尔曼福特、狄克斯特拉算法

本文介绍了BFS(广度优先搜索)、贝尔曼福特算法及狄克斯特拉算法三种经典的最短路径搜索算法。BFS利用队列进行层次遍历,适用于路径权重相同的场景。贝尔曼福特算法通过遍历每条边更新节点的最短距离,适用于存在负权边的情况。狄克斯特拉算法则通过优先选择离起点最近的点来更新其他节点的距离。

关于这三个算法

  1. BFS通过队列实现层次遍历,就是由近及远地往外走,最早到达的一定时最短距离(路径权重相同)。
  2. 贝尔曼福特算法遍历每条边来更新节点的最短距离,第n轮的更新至少会得到由出发点出发,走过n个边的最短路径。所以只要n-1轮,就可以得到最短路径(最坏情况就是把每个节点都经过了,n个顶点n-1条边,想象一下这条路就像个链表)。
  3. 狄克斯特拉算法是每次找到还没遍历过的,离起点最近的点,通过它和它能到达的节点的距离,更新其他节点到起点的距离。当所有点都被看过以后,一定能找出最短路径。
关系
  • 他们都是搜索最短路径的算法,贝尔曼福特算法基于边{O(m+n)}而狄克斯特拉算法基于点{O(m+nlogn)}。
  • 狄克斯特拉算法和BFS比较像,BFS搜索优先级是看层次,而狄克斯特拉算法搜索的优先级是看离起点的远近。因为BFS路径权重都一样,所以只要简单地看下谁先入队谁先搜;
    而狄克斯特拉的话,有时某个点虽然直接和起点相连,但是由于路途比某些间接和起点相连的点还远,就肯定不先搜它啊。这时候可以用由小到大排列的数组(C++可以用set试下)来存储这些还没被遍历的点,近的先出来,先被遍历。
### 狄克斯特拉(Dijkstra)算法实现 狄克斯特拉算法用于求解带权有向图或无向图中,从一个源节点到所有其他节点的最短路径。对于无权图,可以将每的权重视为1。以下是使用邻接矩阵实现的狄克斯特拉算法代码: ```cpp #include <iostream> #include <cstring> #include <climits> using namespace std; const int MAXN = 100; // 狄克斯特拉算法函数 void dijkstra(int graph[MAXN][MAXN], int n, int source) { int dist[MAXN]; // 存储源点到各点的最短距离 bool sptSet[MAXN]; // 标记节点是否已确定最短路径 // 初始化距离数组标记数组 for (int i = 0; i < n; i++) { dist[i] = INT_MAX; sptSet[i] = false; } dist[source] = 0; // 源点到自身的距离为0 // 迭代n次,每次确定一个节点的最短路径 for (int count = 0; count < n - 1; count++) { int u = -1; int minDist = INT_MAX; // 找到未确定最短路径的节点中距离源点最近的节点 for (int v = 0; v < n; v++) { if (!sptSet[v] && dist[v] <= minDist) { minDist = dist[v]; u = v; } } sptSet[u] = true; // 标记该节点已确定最短路径 // 更新与u相邻节点的距离 for (int v = 0; v < n; v++) { if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; } } } // 输出结果 for (int i = 0; i < n; i++) { cout << "从节点 " << source << " 到节点 " << i << " 的最短距离是: "; if (dist[i] == INT_MAX) { cout << "无法到达" << endl; } else { cout << dist[i] << endl; } } } int main() { int n = 5; // 节点数 int graph[MAXN][MAXN] = { {0, 1, 0, 1, 0}, {1, 0, 1, 0, 0}, {0, 1, 0, 1, 1}, {1, 0, 1, 0, 1}, {0, 0, 1, 1, 0} }; int source = 0; // 源节点 dijkstra(graph, n, source); return 0; } ``` ### 广度优先搜索(BFS算法实现 广度优先搜索算法是一种用于遍历或搜索树或图的算法。在无权图中,BFS可以用来求解单源最短路径问题。以下是使用邻接表实现的BFS算法代码: ```cpp #include <iostream> #include <vector> #include <queue> using namespace std; const int MAXN = 100; // BFS算法函数 void bfs(vector<int> adj[], int n, int source) { int dist[MAXN]; // 存储源点到各点的最短距离 for (int i = 0; i < n; i++) { dist[i] = -1; // 初始化为无法到达 } queue<int> q; q.push(source); dist[source] = 0; // 源点到自身的距离为0 while (!q.empty()) { int u = q.front(); q.pop(); // 遍历u的所有邻接节点 for (int v : adj[u]) { if (dist[v] == -1) { dist[v] = dist[u] + 1; q.push(v); } } } // 输出结果 for (int i = 0; i < n; i++) { cout << "从节点 " << source << " 到节点 " << i << " 的最短距离是: "; if (dist[i] == -1) { cout << "无法到达" << endl; } else { cout << dist[i] << endl; } } } int main() { int n = 5; // 节点数 vector<int> adj[MAXN]; // 添加 adj[0].push_back(1); adj[0].push_back(3); adj[1].push_back(0); adj[1].push_back(2); adj[2].push_back(1); adj[2].push_back(3); adj[2].push_back(4); adj[3].push_back(0); adj[3].push_back(2); adj[3].push_back(4); adj[4].push_back(2); adj[4].push_back(3); int source = 0; // 源节点 bfs(adj, n, source); return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值