广度优先搜索 BFS
- 类似于树的按层次遍历,可以利用队列实现。
- 广度优先算法的核心思想是:从初始节点开始,应用算符生成第一层节点,检查目标节点是否在这些后继节点中,若没有,再用产生式规则将所有第一层的节点逐一扩展,得到第二层节点,并逐一检查第二层节点中 是否包含目标节点。若没有,再用算符逐一扩展第二层的所有节点…, 如此依次扩展,检查下去,直到发现目标节点为止。即
- 从图中的某一顶点V0开始,先访问V0
- 访问所有与V0相邻接的顶点V1,V2,…,Vt
- 依次访问与V1,V2,…,Vt相邻接的所有未曾访问过的顶点
- 循此以往,直至所有的顶点都被访问过为止。
- 代码模板:
初始化队列Q; Q = {起点s}; 标记s为已访问; while(Q非空) { for (int i=1;i<=max;++i){ 取Q队首元素u; u出队; if(u==目标状态){ …… }else{ 所有与u相邻且未被访问的点进入队列; 标记u为已访问; } } }
实例:
leetcode100
- 题目如下
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p = [1,2,3], q = [1,2,3] 输出:true 示例 2: 输入:p = [1,2], q = [1,null,2] 输出:false /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */
- 首先完成bfs广度优先搜索函数
- 初始化队列
- 将起点加入队列
- 当队列不为空时,对每一层的节点进行操作。这里需要将所有节点遍历并加入结果数组中。为了区分,null值使用Integer.MAX_VALUE来代替
public ArrayList<Integer> bfs(TreeNode p) { if(p==null) return null; // 初始化队列 Queue<TreeNode> queue = new LinkedList<TreeNode>(); // 将起点加入队列 queue.offer(p); ArrayList<Integer> res = new ArrayList<Integer>(); while(!queue.isEmpty()){ int currentLevelSize = queue.size(); for(int i=1;i<=currentLevelSize;++i){ TreeNode node=queue.poll(); res.add(node.val); if(node.val!=Integer.MAX_VALUE) { if (node.left == null) { queue.offer(new TreeNode(Integer.MAX_VALUE)); } else if (node.left != null) { queue.offer(node.left); } if (node.right == null) { queue.offer(new TreeNode(Integer.MAX_VALUE)); } else if (node.right != null) { queue.offer(node.right); } } } } return res; }
- 在主函数中调用bfs并返回两个列表,比较两个列表,如果一样就返回true,不一样就返回false
public boolean isSameTree(TreeNode p, TreeNode q) { ArrayList<Integer> list1=bfs(p); ArrayList<Integer> list2=bfs(q); if(list1==null && list2==null) return true; if(list1!=null && list2==null) return false; if(list1==null && list2!=null) return false; if(list1.size()!=list2.size()) return false; for(int i=0;i<list1.size();i++){ if(!Objects.equals(list1.get(i), list2.get(i))){ return false; } } return true; }
Leetcode102
- 题目如下
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。 示例: 二叉树:[3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回其层序遍历结果: [ [3], [9,20], [15,7] ]
- 声明一个List存储结果
List<List<Integer>> ret = new ArrayList<List<Integer>>();
- 初始化队列并将起点加入队列
// 初始化队列 Queue<TreeNode> queue = new LinkedList<TreeNode>(); // 将起点加入队列 queue.offer(root);
- 当队列不为空时,取出队首元素,如果该元素满足要求,则存入结果数组中。然后将与该元素相邻的且未访问过的点放入队列中
// 当队列不为空时 while (!queue.isEmpty()) { List<Integer> level = new ArrayList<Integer>(); int currentLevelSize = queue.size(); for (int i = 1; i <= currentLevelSize; ++i) { // 取出队首元素u TreeNode node = queue.poll(); // 元素符合目标状态,加入结果中 level.add(node.val); // 将所有与u相邻的点放入队列 if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } ret.add(level); }