深度优先搜索(DFS)和广度优先搜索(BFS)是图论中两种经典的图遍历算法,它们在解决各种问题如路径查找、迷宫求解、连通性分析等方面有着广泛的应用。
深度优先搜索(DFS)是一种沿着图的边深入直到最后一个顶点,然后回溯并尝试另一条路径的算法。它使用递归或栈来实现,可以看作是树的先序遍历的推广。DFS的特点在于它尽可能深地搜索图的分支,当一条路走到尽头时,它会回溯到上一个顶点,然后继续搜索另一条路径。DFS常用于寻找所有可能的解决方案,例如在解谜游戏或算法竞赛中寻找路径问题。
广度优先搜索(BFS)则是从一个顶点开始,先访问所有相邻的顶点,然后再对每一个相邻顶点,访问它们的相邻顶点,依此类推,逐层向外扩展。BFS通常使用队列来实现,它保证先找到的路径是最短的。因此,BFS常用于寻找最短路径问题,如在社交网络分析或网络爬虫中确定节点间的最短距离。
在实际应用中,选择DFS还是BFS取决于问题的具体需求。例如,如果需要找到所有可能的路径,DFS可能更合适;如果需要找到最短路径,BFS则是更好的选择。此外,DFS和BFS的时间复杂度相同,但BFS的空间复杂度通常较高,因为它需要存储所有已访问的节点。
在实现DFS和BFS时,通常需要维护一个访问标记数组来记录每个节点的访问状态,以避免重复访问。DFS的实现可以使用递归函数,而BFS则需要显式地使用队列来管理待访问的节点。
DFS和BFS的代码实现通常涉及对图的遍历,其中图可以用邻接矩阵或邻接表来表示。在邻接矩阵中,图的顶点通过二维数组表示,而在邻接表中,每个顶点的邻接点通过链表或数组来表示。这两种表示方法各有优缺点,邻接矩阵适用于密集图,而邻接表适用于稀疏图。
在本篇中采用邻接表的方式来构造图。
-
图的建立:
- 使用邻接表表示图,每个顶点有一个链表来存储相邻顶点。
addEdge
方法用于在两个顶点之间添加边。
-
深度优先搜索(DFS):
- 使用布尔数组
visited
来追踪访问过的节点。 - 从起始节点开始,递归访问未访问的相邻节点。
- 使用布尔数组
-
广度优先搜索(BFS):
- 使用队列来存储待访问的节点。
- 从起始节点开始,访问所有相邻节点,然后继续访问这些节点的相邻节点。
代码如下:
import java.util.LinkedList;
public class Solution19 {
// 图的建立广度深度搜索
//使用邻接表来表示图,每个节点都有一个链表,以存储与之相连的节点
public static class Graph{
private int vertices;//顶点数量
private LinkedList<Integer> [] adjacencyList;//邻接表
//构造函数
Graph(int v) {
vertices = v;
adjacencyList = new LinkedList[v];
for (int i = 0; i < v; ++i) {
adjacencyList[i] = new LinkedList<>();
}
}
// 添加边
void addEdge(int v,int w){
adjacencyList[v].add(w);
}
}
//深度优先搜索
//DFS使用递归或栈实现,这里用递归的方法
static class DFS{
private boolean[] visted;
//构造函数
DFS(int vertices){
visted = new boolean[vertices];
}
void dfs(Graph graph,int vertex){
visted[vertex] = true;
System.out.print(vertex + " ");
//递归访问所有相邻节点
for (int n:graph.adjacencyList[vertex]){
if(!visted[n]){
dfs(graph,n);
}
}
}
}
//广度优先搜索
static class BFS{
void bfs(Graph graph,int startVertex){
boolean[] visted=new boolean[graph.vertices];
LinkedList<Integer>queue=new LinkedList<>();
visted[startVertex]=true;
queue.add(startVertex);
while(!queue.isEmpty()){
startVertex=queue.poll();
System.out.print(startVertex + " ");
for(int n:graph.adjacencyList[startVertex]){
if(!visted[n]){
visted[n]=true;
queue.add(n);
}
}
}
}
}
public static void main(String[] args) {
Graph graph=new Graph(4);
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,2);
graph.addEdge(2,0);
graph.addEdge(2,3);
graph.addEdge(3,3);
System.out.println("深度优先搜索(从顶点2开始):");
DFS dfs=new DFS(4);
dfs.dfs(graph,2);
System.out.println("\n广度优先搜索");
BFS bfs=new BFS();
bfs.bfs(graph,2);
}
}