欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【左神算法】二叉树的先序、中序、后序遍历,包括递归方式和非递归方式

程序员文章站 2022-05-16 10:08:19
...

二叉树的先序、中序、后序遍历,包括递归方式和非递归方式

1、二叉树的前序遍历

1.1 思路:

二叉树是一个由left子节点和right子节点 以及val组成的数据结果。而前序遍历的过程就是 根左右。
而实现前序遍历,我们可以用两种方式一种是递归实现,先添加val,递归左右子节点。一种非递归实现,
递归的实现就是系统帮我们自行压栈操作,因此可以借助栈结构来实现。先添加root节点,当栈不为null 保存root.val 以及压入左子节点和右子节点。如此反复。
时间复杂度:二叉树的遍历需要花费O(n) 如果不计算栈的消耗
空间复杂度:O(n) 无论是递归还是非递归 都需要进行O(n)

1.2 递归实现 code

 //栈
    public List<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> res = new ArrayList<>(); 
        if(root == null)    return res;

        Stack<TreeNode> stack = new Stack();
        stack.push(root);

        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            res.add(node.val);

            if(node.right!=null){
                stack.push(node.right);
            }

            if(node.left != null){
                stack.push(node.left);
            }            
        }  
        return res;
    }

1.3 非递归实现 code

public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root == null)    return res;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            res.add(node.val);
            if(node.right != null){
                stack.push(node.right);
            }

            if(node.left != null){
                stack.push(node.left);
            }
        }
        return res;
    }

2、二叉树的中序遍历

2.1 思路:

中序遍历和前序遍历的递归版相似,只需要修改添加的位置。
而非递归版借助栈 先压入左子节点,如果左子节点为null 弹出 添加值,然后查看右子节点。
时间复杂度:O(n)
空间复杂度:O(n)

2.2 递归实现 code

public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList();
        helper(root,result);
        return result;
    }

    public static void helper(TreeNode root,List<Integer> result){
        if(root!=null){
            //左
            if(root.left!=null){
                helper(root.left,result);
            }
            //中
            result.add(root.val);
            //右
            if(root.right!=null){
                helper(root.right,result);
            }
        }
    }

2.3 非递归实现 code

	//借助stack
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root == null)    return res;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while( cur!=null || !stack.empty()){
            //添加左节点
            while(cur!=null){
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            res.add(cur.val);
            //push右节点
            cur = cur.right;
        }
        return res;
    }

3、二叉树的后序遍历

3.1 思路:

递归版 直接 修改add的位置
非递归版 后序遍历 为 左右根 而前序遍历为根左右 有没有发现 如果将左右的位置改变 然后在逆序就是后序遍历的结果了。这里借助两个栈。一个栈存储节点,另一个栈存储数据,将根右左的值添加 然后pop 就是结果。
时间复杂度:O(n)
空间复杂度:O(n)

3.2 递归实现 code

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root == null)    return res;
        helper(root,res);
        return res;
    }

    public void helper(TreeNode node,List<Integer> res){
        if(node!=null){
            if(node.left!=null){
                helper(node.left,res);
            }

            if(node.right!=null){
                helper(node.right,res);
            }
            res.add(node.val);
        }
    }

3.3 非递归实现 code

	//左右根   先序遍历 根左右    根右左 
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root==null)  return res;
        Stack<Integer> stack = new Stack();//存储数据
        Stack<TreeNode> nodeStack = new Stack();//存储节点

        nodeStack.push(root); //先存储根节点
        while(!nodeStack.isEmpty()){
            TreeNode node = nodeStack.pop();
            stack.push(node.val);
            if(node.left!=null){
                nodeStack.push(node.left);
            }

            if(node.right!=null){
                nodeStack.push(node.right);
            }
        }
        while(!stack.isEmpty()){
            res.add(stack.pop());
        }
        return res;
    }