树的广度优先搜索BFS
1. 基本思想
思路:输出与当前节点直接相连的节点,直至将与之相连的节点全部输出完,则进入下一层,直至全部节点都被遍历一遍。
如图所示有一颗二叉树,根节点为A。输出其广度优先搜索的值。
第一步:将A输出,此时输出为A;
第二步:将A的左孩子输出,此时输出为A B;再将A的右孩子输出,此时输出为A BC;
第三步:此时输出为A BC,而A已经输出了,那么便输出B的左右孩子,此时输出为A BC DE;再输出C的左右孩子,此时输出为A BC DEFG。
第四步:再输出D的左右孩子,发现为空;
第五步:再输出E的左右孩子,发现为空;
第六步:再输出F的左右孩子,发现为空;
第七步:再输出G的左右孩子,发现为空。遍历结束,输出为ABCDEF。
2.代码实现可能需要的数据结构(JAVA)
2.1 顺序队列
特点:先进先出
常用操作:
- 定义一个队列(<>内的数据类型根据需要有Character、Sting、Integer等)
Queue< Character >queue = new LinkedList< Charccter >(); - queue.offer():在队尾添加一个元素;
- queue.poll():移除队首元素并返回该元素;
- queue.peek():返回队首元素,不移除;
- queue.isEmpty():判断队列是否为空,是则返回true,否则返回false。
2.2 哈希表
常用操作:
- 定义一个哈希表
Map< Integer,Integer > hashtable = new HashMap< Integer. Integer >();; - put(key,value):向哈希表中加入一对新的键值对;
- get(key):通过关键字取其值;
- remove(key):根据关键字删除键值对;
- isEmpty():查看哈希表是否为空;
- containsKey(key):判断哈希表中是否存在关键字key。
3. 将基本思想转换为代码思想
- 给每个节点设置一个flag值,用于判断当前节点是否已经输出。flag=1表示已输出,flag=0表示未输出。每个节点的flag值可以用键值对实现;
- 数据结构使用队列queue,特点是先进先出,符合BFS的思想;
- 首先将根节点入队(队里的第一个节点);
- 将根节点出队(输出),与根节点相邻的所有节点入队;
- 队首出队,将该节点的所有节点加入队列;
- 重复操作5,直至全部输出。
4.转换成代码(JAVA实现,仅供思路参考)
public String bfs(TreeNode root){
if(root == null) return '';
Queue<TreeNode> queue = new LinkedList<TreeNode>();
Map<TreeNode,Character> hashmap = new HashMap<TreeNode,Character>();
String string = '';
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
hashmap.put(root,1);
if(node.left!=null&&hashmap.get(node.left)!=1) queue.offer(node.left);
if(node.right!=null&&hashmap.get(node.right)!=1) queue.offer(node.right);
string = string + node.val;
}
return string;
}
5.实例
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if(root == null) return new ArrayList<>();
// res为最终返回的结果
List<List<Integer>> res = new ArrayList<>();
// 新建队列
Queue<TreeNode> queue = new LinkedList<TreeNode>();
// 根节点入队
queue.offer(root);
// 如果队列非空
while(!queue.isEmpty()){
// 用count来控制每一层的节点输出
int count = queue.size();
// 用list来进行每层的输出
List<Integer> list = new ArrayList<Integer>();
while(count>0){
// 队首出队
TreeNode node = queue.poll();
// 队首出队入列
list.add(node.val);
// 左孩子入队
if(node.left != null) queue.offer(node.left);
// 右孩子入队
if(node.right != null) queue.offer(node.right);
// 出队后该层数量减1
count--;
}
// 将该层加到最终输出的值中
res.add(list);
}
// 返回最终输出值res
return res;
}
}