用非递归遍历二叉树

以前一直认为递归遍历二叉树是天经地义,今天遇到了要求使用非递归来遍历二叉树,决定思考一下这个问题

前序遍历

用栈来实现:
1.开始先将头结点加入栈中
2.弹出栈。输出弹出元素
3.将节点右元素入栈
4.将节点左元素入栈
重复 2–4知道栈空

为什么要先压入右元素呢?因为我们要确保先访问到的是左节点

前序遍历代码:

 public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();

        if(root == null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while(!stack.isEmpty()){
            TreeNode now = stack.pop();
            list.add(now.val);
            if(now.right != null) stack.push(now.right);
            if(now.left != null) stack.push(now.left);
        }
        return list;

    }

后序遍历

和前序遍历很类似
用栈来实现:
1.开始先将头结点加入栈中
2.弹出栈。将节点的值加入列表的头结点(也可以直接加入一个队列)
3.将节点左元素入栈
4.将节点右元素入栈
重复 2–4直到栈空

简单的说就是将序列倒序输出

 public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if(root == null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode now = stack.pop();
            list.add(0,now.val);
            if(now.left != null) stack.push(now.left);
            if(now.right != null) stack.push(now.right);
        }
        return list;

    }

另一种更常规的后续非递归遍历写法

public ArrayList<Integer> postorderTraversal2(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if(root == null) return list;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode pre  = null;
        while(!stack.isEmpty()){
            TreeNode now = stack.peek();
            if((now.left == null && now.right == null) || (pre != null && (now.left == pre || now.right == pre))){
                list.add(now.val);
                stack.pop();
                pre = now;
            }
            else{
                if(now.right!=null) stack.push(now.right);
                if(now.left !=null) stack.push(now.left);
            }
        }
        return list;

    }

中序遍历

对于任一结点p:

step 1:若其左孩子不为空,则将p入栈,并将p的左孩子置为当前的p。然后对当前结点p再进行相同的处理。

step 2:若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将栈顶结点的右孩子置为当前的P结点。

step 3:直到p为NULL并且栈为空则遍历结束。

 public ArrayList<Integer> inorderTraversal2(TreeNode root){

        ArrayList<Integer> list = new ArrayList<>();
        if(root == null) return list;

        Stack<TreeNode> stack = new Stack<>();
        TreeNode p = root;

        while (!stack.isEmpty() || p != null) {
            while(p != null){
                stack.push(p);
                 p = p.left;
            }
            if(!stack.isEmpty()){
                p = stack.pop();
                list.add(p.val);
                p = p.right;
            }
        }

        return list;
    }

猜你喜欢

转载自blog.csdn.net/ymybxx/article/details/80269982