一. 广度搜索
Breadth-First Search(BFS)是一种图遍历算法,用于从一个起始节点开始,逐层扩展到与起始节点距离为1的节点,然后是距离为2的节点,以此类推。BFS通常用于查找两个节点之间的最短路径,或者确定是否存在从一个节点到另一个节点的路径。
import java.util.LinkedList;
import java.util.Queue;
public class BFSSearch {
public static boolean bfs(int[][] graph, int start, int end) {
int n = graph.length;
boolean[] visited = new boolean[n];
Queue<Integer> queue = new LinkedList<>();
visited[start] = true;
queue.add(start);
while (!queue.isEmpty()) {
int node = queue.poll();
if (node == end) {
return true; // 找到了从起点到终点的路径
}
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.add(neighbor);
}
}
}
return false; // 无法找到从起点到终点的路径
}
public static void main(String[] args) {
int[][] graph = {
{1, 2}, // 节点0相邻的节点是1和2
{0, 3, 4}, // 节点1相邻的节点是0、3和4
{0, 5}, // 节点2相邻的节点是0和5
{1}, // 节点3相邻的节点是1
{1}, // 节点4相邻的节点是1
{2} // 节点5相邻的节点是2
};
int start = 0; // 起点
int end = 3; // 终点
boolean found = bfs(graph, start, end);
if (found) {
System.out.println("从节点 " + start + " 到节点 " + end + " 存在路径。");
} else {
System.out.println("从节点 " + start + " 到节点 " + end + " 不存在路径。");
}
}
}
步骤:
- 创建一个队列(通常是使用 LinkedList 实现),用于存储待处理的节点。
- 将起点 start 放入队列,并将其标记为已访问(可以使用一个布尔数组 visited 来标记节点是否被访问过,这可以避免重复访问节点)。
- 进入循环,检查队列是否为空。如果队列为空,表示无法找到从起点到终点的路径,搜索结束。
- 在每次循环迭代中,从队列中取出队头的节点(当前节点),将其索引保存在 node 变量中。
- 检查 node 是否等于终点 end。如果相等,表示已找到从起点到终点的路径,搜索结束,返回 true。
- 如果 node 不等于终点,遍历当前节点的相邻节点(通常是通过邻接列表 graph[node] 获取的)。对于每个相邻节点:
- 如果该相邻节点尚未被访问(即 visited[neighbor] 为 false),则标记它为已访问(visited[neighbor] = true)。
- 将相邻节点的索引放入队列中,以便稍后处理。
- 返回第 3 步,重复此过程,直到队列为空或找到目标节点。如果队列为空,表示无法找到路径,返回 false。
总的来说,BFS 使用队列来存储待处理的节点,以广度优先的方式遍历图。它从起点开始,一层一层地扩展,直到找到终点或处理完所有可达节点。此外,visited 数组确保不会多次访问同一节点,防止陷入无限循环。
二. 深度搜索
深度优先搜索(Depth-First Search,DFS)是一种遍历或搜索树或图的算法,它从起点开始,沿着路径一直向前,直到无法再继续或者达到目标节点,然后回溯到上一个节点,继续搜索。DFS 使用栈(通常是递归调用的函数调用栈)来存储待处理的节点。
function dfs(node, target):
if node == target:
return true // 找到目标节点
if node is visited:
return false // 已经访问过,避免无限循环
mark node as visited // 标记节点为已访问
for each neighbor in neighbors of node:
if dfs(neighbor, target):
return true // 递归搜索,如果找到目标节点,返回true
return false // 没有找到目标节点
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class DepthFirstSearch {
private int vertices;
private List<List<Integer>> adjacencyList;
public DepthFirstSearch(int vertices) {
this.vertices = vertices;
adjacencyList = new ArrayList<>(vertices);
for (int i = 0; i < vertices; i++) {
adjacencyList.add(new ArrayList<>());
}
}
public void addEdge(int source, int destination) {
adjacencyList.get(source).add(destination);
}
public boolean dfs(int start, int target) {
boolean[] visited = new boolean[vertices];
Stack<Integer> stack = new Stack<>();
stack.push(start);
while (!stack.isEmpty()) {
int current = stack.pop();
visited[current] = true;
if (current == target) {
return true; // 找到目标节点
}
for (int neighbor : adjacencyList.get(current)) {
if (!visited[neighbor]) {
stack.push(neighbor);
}
}
}
return false; // 没有找到目标节点
}
public static void main(String[] args) {
DepthFirstSearch graph = new DepthFirstSearch(7);
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 3);
graph.addEdge(1, 4);
graph.addEdge(2, 5);
graph.addEdge(3, 6);
int start = 0;
int target = 6;
if (graph.dfs(start, target)) {
System.out.println("Target node " + target + " is reachable from node " + start);
} else {
System.out.println("Target node " + target + " is not reachable from node " + start);
}
}
}