二叉树的BFS和DFS
BFS(广度优先搜索)
树的BFS遍历是按层来搜索的
public static void BFS(TreeNode root){
if(root==null){
return;
}
//使用一个队列来保存每层的数据
Queue<TreeNode> queue = new LinkedList<>();
//添加第一层的数据
queue.offer(root);
while (!queue.isEmpty()){
//先拿到一层的节点数量
int len = queue.size();
//遍历一层的节点,并把节点的子节点加入到队列
//因为这个for循环只取出当前层的节点
//所以for循环结束的时候,queue的头节点就是下一层的节点了
for (int i = 0; i < len; i++) {
TreeNode node = queue.poll();
System.out.println(node.val);//处理数据
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
}
}
DFS(深度优先搜索)
深度优先搜索分为前序遍历、中序遍历、后续遍历 也就是root节点的访问顺序
递归
DFS推荐使用递归实现,代码比较简单易懂
public static void DFS(TreeNode root){
if(root==null){
return;
}
System.out.println(root.val);
//前序遍历在这里处理数据
DFS(root.left);
//中序遍历在这里处理数据
DFS(root.right);
//后续遍历在这里处理数据
}
非递归
递归主要就是运用了方法的调用栈,非递归的话我们只要自己实现一个栈来保存数据即可
- 前序遍历
//前序遍历
public static void DFSStackPreOrder(TreeNode root){
//root left right的遍历顺序
if(root==null){
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();//root先访问到,所以先出栈
if(node.right!=null){//right是最后访问到的,所以先入栈
stack.push(node.right);
}
if(node.left!=null){
stack.push(node.left);
}
System.out.println(node.val);//处理数据
}
}
- 中序遍历
public static void DFSStackInOrder(TreeNode root){
//left root right的遍历顺序
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty()||root!=null){
if(root!=null){
//当前子树左节点不为空的话,
//先将左节点入栈
stack.push(root);
root = root.left;
}else{
//当前子树左节点为空,
//说明遍历到了最左边了,
//要开始遍历子节点的有右子树了
root = stack.pop();//出栈,拿到的是子节点的最左边
System.out.println(root.val);//处理数据
root = root.right;//把root设置成右子树,开始遍历右子树
}
}
}
- 后续遍历
public static void DFSStackPostOrder(TreeNode root){
//left right root的遍历顺序
if(root==null){
return;
}
//后续遍历需要借助一个链表来先保存结果
List<Integer> result = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
//root是最后访问到的,
// 所以需要每次都在链表头节点插入,
// 这样最后root就会排在链表尾部
result.add(0,root.val);
if(root.left!=null){
stack.push(root.left);
}
if(root.right!=null){
stack.push(root.right);
}
root = stack.pop();
}
//到这里,链表里的数据就是最后结果了
System.out.println(result);
}
辅助的代码,生成树
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
public static TreeNode generate(Integer[] a) {
Queue<TreeNode> queue = new ArrayDeque<>();
TreeNode root = new TreeNode(a[0]);
queue.add(root);
for (int i =1;i<a.length;i+=2) {
TreeNode treeNode = queue.remove();
if (a[i] != null) {
treeNode.left = new TreeNode(a[i]);
queue.add(treeNode.left);
}
if (i + 1 < a.length && a[i + 1] != null) {
treeNode.right = new TreeNode(a[i + 1]);
queue.add(treeNode.right);
}
}
return root;
}
}
例如这样的树
3
/ \
9 20
/ \
15 7
构造树
TreeNode root = TreeNode.generate(new Integer[{3,9,20,null,null,15,7});