算法day11 | Java | 二叉树 | 递归遍历、迭代遍历、统一迭代、层序遍历

38 阅读2分钟

Java

  • 二叉树基础

  • 堆就是一个完全二叉树(优先队列就是一个大堆)

  • list反转 Collections.reverse(res); (注:List<Integer> res = new ArrayList<>();)

  • List<List<Integer>>

List<List<Integer>> res = new ArrayList<List<Integer>>();
需要注意的是,在使用 List<List<Integer>> 时,需要先定义外层列表 res,再在每个元素中定义内层列表。

List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
res.add(list1); //res添加
 
List<Integer> list2 = new ArrayList<>();
list2.add(4);
list2.add(5);
list2.add(6);
res.add(list2);//res添加

res为:
[  
  [1, 2, 3],  
  [4, 5, 6]  
]

递归遍历

递归三部曲

①确定递归函数的参数 和 返回值

②确定终止条件

③确定单层递归的逻辑

  • 以前序遍历为例
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preorder(root,res);
        return res;
    }
    void preorder(TreeNode cur, List<Integer> res) {
        if(cur == null) {
            return;
        }
        res.add(cur.val);
        preorder(cur.left ,res);
        preorder(cur.right ,res);
    }
}

迭代遍历

理论上讲,所有的递归都可以用栈模拟出来。

前序后序做法是一样的,因为前序的顺序是中左右,后序是左右中,可以reverse反转得到。

以及前序遍历时的注意点是,入栈顺序是先放右节点再放左节点,因为出栈顺序相反。

  • 以后序遍历为例
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        //左右中  中右左
        List<Integer> res = new ArrayList<>();
        if(root == null) return res;
        Stack<TreeNode>s = new Stack<>();
        s.push(root);
        while(!s.isEmpty()) {
            TreeNode cur = s.pop();
            res.add(cur.val);
            if(cur.left!=null) s.push(cur.left);
            if(cur.right!=null) s.push(cur.right);
        }
        Collections.reverse(res);
        return res;
    }
}
  • 中序遍历

中序节点和前序后续不一样,因为前序遍历的访问顺序&处理顺序是一样的。

中序遍历先访问根节点,但要等左子树处理完之后才处理根节点,所以需要【有标记】。最简单的标记就是入栈时多加一个空节点。根节点是在第二次访问时才处理,所以在第一次访问后就加一个空节点。

中序遍历解法:

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer>res = new ArrayList<>();
        Stack<TreeNode>stack = new Stack<>();
        if(root==null) return res;
        stack.push(root);
        while(!stack.isEmpty()) {
            TreeNode top = stack.peek();
            if(top!=null) {
                stack.pop();
                if(top.right!=null) {stack.push(top.right);}
                stack.push(top); 
                stack.push(null);
                if(top.left!=null) {stack.push(top.left);}

            } else{
                //遇到null表示左子树处理完了
                stack.pop(); //弹出null
                TreeNode cur = stack.pop(); //弹出根节点
                res.add(cur.val);
            }
        }
        return res;
    }
}

层序遍历

  • Queueque = new LinkedList<>();
  • List<List>res = new ArrayList<List>();
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode>que = new LinkedList<>();
        List<List<Integer>>res = new ArrayList<List<Integer>>();
        if(root == null) return res;
        que.offer(root);
        while(!que.isEmpty()) {
            int size = que.size();
            List<Integer>list = new ArrayList<>();
            while(size > 0) {
                TreeNode node = que.poll();
                list.add(node.val);

                if(node.left!=null)que.offer(node.left);
                if(node.right!=null)que.offer(node.right);
                size--;
            }
            res.add(list);
        }
        return res;
    }
}