BFS
BFS 我觉得可以从两个方向理解。第一种,对某个树或者图的数据结构而言,就是某个节点相连接的节点都遍历,再不断对刚遍历的节点做同样的操作直到最后遍历完所有节点。第二种,当数据结构是树形的时候这个规律可以衍生为按照层来遍历。按照当前的理解,BFS 一般可以用一个队列来实现,这是因为按照 FIFO 的特性。对于节点相连接的节点都遍历的时候,遍历结束了之后需要从最第一个遍历的节点开始。
输出:
1, 2, 3, 4, 5, 6, 7, 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Tree { private ArrayList<Integer> order = new ArrayList<>(); ArrayList bfsSearch(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while(!queue.isEmpty()) { TreeNode node = queue.poll(); if (node != null) { order.add(node.value); queue.offer(node.left); queue.offer(node.right); } } return order; } }
|
层序遍历二叉树
在 BFS 的基础上,期待上面的遍历结果能已分层的形式输出:
1
2 3
4 5 6
7 8
这个问题在《编程之美》和《剑指 Offer》上面都出现过。
其实只要模拟一下队列的出入过程就能发现,BFS 过程中维护的队列总是在不断的 offer 和 poll。当第 1 层的 #1 poll 的时候,第 2 层的 #2,#3 offer…, 第 2 层 #2 poll 的时候,第 3 层的 #4, #5 offer,第二层的 #3 poll 的时候。.. 也就是说,如果能知道第二层层结束了那么就有办法了。
回过头再看,第一层的 #1 两个子节点 offer 之后。队列的 size 变成了 2。如果维持一个计数器表示当计数器的值从在 [0, size] 之间的时候表示第二层正在 poll, 第三层正在 offer,那么就能表示层级的变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Solution {
ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) { ArrayList<ArrayList<Integer>> ret = new ArrayList<>(); if (pRoot == null) return ret; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(pRoot);
while(!queue.isEmpty()) { ArrayList<Integer> thisLevel = new ArrayList<>(); int low = 0, high = queue.size(); for (int i = low; i < high; i++) { TreeNode node = queue.poll(); thisLevel.add(node.val); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } ret.add(thisLevel); } return ret; } }
|