双向广度优先搜索算法步骤:
-
初始化:
- 从起始节点开始,分别初始化两个队列
q_forward
和q_backward
。 - 将起始节点分别放入这两个队列中。
- 初始化两个集合
visited_forward
和visited_backward
用于记录已访问的节点。
- 从起始节点开始,分别初始化两个队列
-
循环:
- 在循环中,分别从
q_forward
和q_backward
中取出一个节点进行扩展。 - 对于
q_forward
,从当前节点开始探索其相邻节点,并将未访问过的相邻节点加入到q_forward
中。 - 对于
q_backward
,从当前节点开始探索其相邻节点,并将未访问过的相邻节点加入到q_backward
中。 - 在每次扩展节点时,检查两个队列中是否存在相同的节点,如果存在则找到了一条双向路径。
- 如果找到双向路径,停止搜索并合并两个路径。
- 在循环中,分别从
-
终止条件:
- 当两个队列中存在相同的节点,或者两个队列中的节点都被完全探索过后,算法终止。
C++代码示例:
#include <iostream>
#include <queue>
#include <unordered_set>
#include <vector>using namespace std;// 双向广度优先搜索
bool bidirectional_bfs(vector<vector<int>>& graph, int start, int target) {queue<int> q_forward, q_backward;unordered_set<int> visited_forward, visited_backward;q_forward.push(start);q_backward.push(target);visited_forward.insert(start);visited_backward.insert(target);while (!q_forward.empty() && !q_backward.empty()) {// 扩展正向队列int curr_forward = q_forward.front();q_forward.pop();for (int neighbor : graph[curr_forward]) {if (!visited_forward.count(neighbor)) {visited_forward.insert(neighbor);q_forward.push(neighbor);}if (visited_backward.count(neighbor)) {cout << "Path found!";return true;}}// 扩展反向队列int curr_backward = q_backward.front();q_backward.pop();for (int neighbor : graph[curr_backward]) {if (!visited_backward.count(neighbor)) {visited_backward.insert(neighbor);q_backward.push(neighbor);}if (visited_forward.count(neighbor)) {cout << "Path found!";return true;}}}cout << "Path not found!";return false;
}
上为邻接表形式,接下来给出矩阵形式:
#include <iostream>
#include <queue>
#include <unordered_set>
#include <vector>
using namespace std;
int rows,cols;void showcurboard(int** boa){for(int i=0;i<rows;i++){for(int j=0;j<cols;j++)cout<<boa[i][j];cout<<endl;}
}struct Coordinate {int x;int y;Coordinate(int _x, int _y) : x(_x), y(_y) {}
};
struct PairHash {template <class T1, class T2>std::size_t operator () (const std::pair<T1, T2> &pair) const {auto hash1 = std::hash<T1>{}(pair.first);auto hash2 = std::hash<T2>{}(pair.second);return hash1 ^ hash2;}
};
vector<pair<int, int>> directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool bidirectional_bfs(int** matrix, int begina, int beginb, int enda, int endb) {queue<Coordinate> q_forward, q_backward;unordered_set<pair<int, int>, PairHash> visited_forward, visited_backward;q_forward.push(Coordinate(begina, beginb));q_backward.push(Coordinate(enda, endb));visited_forward.insert({begina, beginb});visited_backward.insert({enda, endb});while (!q_forward.empty() && !q_backward.empty()) {Coordinate curr_forward = q_forward.front();q_forward.pop();for (auto& dir : directions) {int new_x = curr_forward.x + dir.first;int new_y = curr_forward.y + dir.second;if (new_x >= 0 && new_x < rows && new_y >= 0 && new_y < cols && visited_forward.count({new_x, new_y}) == 0) {visited_forward.insert({new_x, new_y});if (visited_backward.count({new_x, new_y}) > 0) {return true;}q_forward.push(Coordinate(new_x, new_y));}}Coordinate curr_backward = q_backward.front();q_backward.pop();for (auto& dir : directions) {int new_x = curr_backward.x + dir.first;int new_y = curr_backward.y + dir.second;if (new_x >= 0 && new_x < rows && new_y >= 0 && new_y < cols && visited_backward.count({new_x, new_y}) == 0) {visited_backward.insert({new_x, new_y});if (visited_forward.count({new_x, new_y}) > 0) {return true;}q_backward.push(Coordinate(new_x, new_y));}}}return false;
}int main()
{int a,b;cin>>rows>>cols>>a>>b;int** board=new int*[rows];for(int i=0;i<rows;i++){board[i]=new int[cols];fill(board[i],board[i]+cols,0);}//showcurboard(board);return 0;
}