文章目录
- 前言:
- 应用:
前言:
BFS(广度优先遍历,Breadth First Search)及DFS(深度优先遍历,Depth First Search)是遍历树或图的两种最常用的方法。本文简单的讲解在面对树或者图的问题时,使用BFS及DFS解答题目时的思路及实现。
1.BFS:一层一层遍历。借助队列。
主要思想:
是从起始点开始,将其邻近的所有顶点都加到一个队列(FIFO)中去,然后标记下这些顶点离起始顶点的距离为1.最后将起始顶点标记为已访问,今后就不会再访问。然后再从队列中取出最先进队的顶点A,也取出其周边邻近节点,加入队列末尾,最后离开这个顶点A。依次下去,直到队列为空为止。从上面描述的过程我们知道每个顶点被访问的次数最多一次(已访问的节点不会再访问)。
2.DFS:利用递归或栈
主要思想:
DFS是从起始顶点开始,递归访问其所有邻近节点,比如A节点是其第一个邻近节点,而B节点又是A的一个邻近节点,则DFS访问A节点后再访问B节点,如果B节点有未访问的邻近节点的话将继续访问其邻近节点,否则继续访问A的未访问邻近节点,当所有从A节点出去的路径都访问完之后,继续递归访问除A以外未被访问的邻近节点。
应用:
1.树
定义二叉树:
//Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
(1)BFS
使用队列实现BFS:
//使用Queue实现BFS
public void BFSWithQueue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root != null)
queue.add(root);
while (!queue.isEmpty()) {
TreeNode treeNode = queue.poll();
//在这里处理遍历到的TreeNode节点
if (treeNode.left != null)
queue.add(treeNode.left);
if (treeNode.right != null)
queue.add(treeNode.right);
}
}
(2)DFS
递归遍历二叉树:
//DFS递归实现
public void DFSWithRecursion(TreeNode root) {
if (root == null)
return;
//在这里处理遍历到的TreeNode节点
if (root.left != null)
DFSWithRecursion(root.left);
if (root.right != null)
DFSWithRecursion(root.right);
}
使用栈实现DFS:
//DFS的迭代实现版本(Stack)
public void DFSWithStack(TreeNode root) {
if (root != null)
return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode treeNode = stack.pop();
//在这里处理遍历到的TreeNode
if (treeNode.right != null)
stack.push(treeNode.right);
if (treeNode.left != null)
stack.push(treeNode.left);
}
}
2.图
邻接矩阵:
特点:邻接矩阵存储起来比较浪费空间,但是使用起来比较节省时间。
邻接表:特点:邻接表存储起来比较节省空间,但是使用起来就比较耗时间
public class Graph{
private int v;//顶点个数
private LinkedList<Integer> adj[];
Graph(int v){
this.v=v;
adj=new LinkedList[v];
for(int i=0;i<v;i++){
adj[i]=new LinedList<>();
}
}
public void addEdge(int s,int t){//无向图一条边要存两次
adj[s].add(t);
adj[t].add(s);
}
}
**图和树的最大区别在于图的下一个节点可能指向已访问过的节点。**因此在使用BFS及DFS遍历时,应维护一个Set,Set中存放已被访问过的节点,在遍历时先判断节点未被访问过再遍历即可。
(1)BFS
代码实现:
//使用Queue实现BFS
public void BFSWithQueue(Node root) {
Queue<Node> queue = new LinkedList<>();
if (root != null)
queue.add(root);
Set<Node> visited = new HashSet<>();
while (!queue.isEmpty()) {
Node node = queue.poll();
visited.add(node);
//在这里处理遍历到的Node节点
if (node.children != null) {
for (Node child : node.children) {
if (child != null && !visited.contains(child){
queue.add(child);
}
}
}
}
}
(2)DFS:
递归实现图的遍历:
!!!有待修改
Set<Node> visited = new HashSet<>();
public void DFSWithStack(Graph root,int v){
if(root!=null)
return;
while(root!=0){
visited.add(node);
}
}
借助栈实现图的遍历
//DFS的迭代实现版本(Stack)
public void DFSWithStack(Node root) {
if (root != null)
stack.push(root);
Stack<TreeNode> stack = new Stack<>();
Set<Node> visited = new HashSet<>();
while (!stack.isEmpty()) {
TreeNode treeNode = stack.pop();
visited.add(node);
//在这里处理遍历到的TreeNode
if (child != null && !visited.contains(child){
stack.push(child);
}
}
}