广度优先搜索算法
广度优先搜索算法(BFS)是一种用于图和树的搜索和遍历的算法,它的应用广泛且深受欢迎。本文将介绍广度优先搜索算法的起源、原理、应用、复杂度,以及通过C++和Java实现该算法。
1.介绍
起源
广度优先搜索算法最早由爱德华·福克斯在1951年提出,用于解决迷宫问题。后来,这一算法被广泛应用于计算机科学领域。
原理和思想
广度优先搜索算法的原理是从起始节点开始,逐层地向外扩展搜索,即先访问起始节点的所有相邻节点,然后再访问这些节点的相邻节点,依次类推,直到找到目标节点或者遍历完所有节点。该算法通常使用队列来实现,以确保按照层级顺序进行搜索。
2. 应用
广度优先搜索算法在现实生活中有许多应用(可能吧),例如:
- 社交网络中的好友推荐:通过广度优先搜索算法可以找到与用户关系最近的好友,用于推荐好友或者扩展社交圈子。
- 迷宫问题的解决:广度优先搜索算法可以帮助寻找迷宫中的最短路径,或者找到迷宫的出口。
- 路径规划:在地图应用中,广度优先搜索算法可以用于寻找最短路径,规划行车路线或者公共交通路线。
3. 算法复杂度和优缺点
时间复杂度和空间复杂度
在最坏情况下,广度优先搜索算法的时间复杂度为O(V + E),其中V是节点数,E是边数。空间复杂度取决于队列的大小,通常为O(V)。
优缺点
在某些特定的图结构中,广度优先搜索算法的时间复杂度可能比深度优先搜索算法更低,尤其是在搜索最短路径时。然而,广度优先搜索算法的空间复杂度通常较高,尤其是在图的宽度较大时。与深度优先搜索算法相比,广度优先搜索算法通常更适合寻找最短路径或者层级遍历。
4. C++和Java实现
简单遍历输出
C++
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector<int> adj[100];
bool visited[100];
void bfs(int start) {
queue<int> q;
q.push(start);
visited[start] = true;
while (!q.empty()) {
int v = q.front();
q.pop();
cout << v << " ";
for (int u : adj[v]) {
if (!visited[u]) {
q.push(u);
visited[u] = true;
}
}
}
}
int main() {
bfs(0);
return 0;
}
Java实现
import java.util.LinkedList;
import java.util.Queue;
public class BreadthFirstSearch {
static LinkedList<Integer>[] adj;
static boolean[] visited;
static void bfs(int start) {
Queue<Integer> queue = new LinkedList<>();
queue.add(start);
visited[start] = true;
while (!queue.isEmpty()) {
int v = queue.poll();
System.out.print(v + " ");
for (int u : adj[v]) {
if (!visited[u]) {
queue.add(u);
visited[u] = true;
}
}
}
}
public static void main(String[] args) {
bfs(0);
}
}
小优化
如果要优化可以使用双向BFS:同时从起始节点和目标节点开始搜索,直到两个搜索路径相遇,就是最短路径。这种方法可以显著减少搜索的时间复杂度,尤其是在寻找最短路径时,但前提是知道终点。定义两个队列,加个判断即可。但实际做起来还是有点复杂,根据题目不同有一定调整。
模拟迷宫问题
双向BFS:
//#include <bits/stdc++.h>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// 定义迷宫的大小
const int N = 5;
const int M = 5;
// 定义迷宫
int maze[N][M] = {
{0, 1, 0, 0, 0},
{0, 1, 0, 1, 0},
{0, 0, 0, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 0, 1, 0}
};
// 定义方向数组
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
// 定义节点结构体
struct Node {
int x, y, dist;
};
// 双向BFS函数
int bidirectionalBFS(Node start, Node end) {
vector<vector<bool>> visitedFromStart(N, vector<bool>(M, false));
vector<vector<bool>> visitedFromEnd(N, vector<bool>(M, false));
queue<Node> qStart, qEnd;
qStart.push(start);
qEnd.push(end);
visitedFromStart[start.x][start.y] = true;
visitedFromEnd[end.x][end.y] = true;
while (!qStart.empty() && !qEnd.empty()) {
int ans = -1;
ans = qStart.front().dist + qEnd.front().dist;
if (ans <= 10) {
return ans;
}
Node currentStart = qStart.front();
qStart.pop();
Node currentEnd = qEnd.front();
qEnd.pop();
for (int i = 0; i < 4; i++) {
int newX = currentStart.x + dir[i][0];
int newY = currentStart.y + dir[i][1];
if (newX >= 0 && newX < N && newY >= 0 && newY < M && maze[newX][newY] == 0 && !visitedFromStart[newX][newY]) {
visitedFromStart[newX][newY] = true;
Node next = {newX, newY, currentStart.dist + 1};
qStart.push(next);
}
}
for (int i = 0; i < 4; i++) {
int newX = currentEnd.x + dir[i][0];
int newY = currentEnd.y + dir[i][1];
if (newX >= 0 && newX < N && newY >= 0 && newY < M && maze[newX][newY] == 0 && !visitedFromEnd[newX][newY]) {
visitedFromEnd[newX][newY] = true;
Node next = {newX, newY, currentEnd.dist + 1};
qEnd.push(next);
}
}
}
return -1; // 如果找不到路径,返回-1
}
int main() {
Node start = {0, 0, 0};
Node end = {4, 4, 0};
int steps = bidirectionalBFS(start, end);
if (steps != -1) {
cout << "最短路径长度为:" << steps << endl;
} else {
cout << "有毛病!" << endl;
}
return 0;
}
编辑器润色了一下,自我感觉良好
部分内容百度
感谢阅读