二叉树6:迭代法实现二叉树的遍历

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树6:迭代法实现二叉树的遍历相关的知识,希望对你有一定的参考价值。

我们在《递归迭代和分治》专题就介绍过,递归能做的迭代一定能做,但是可能会比较复杂。但是与递归相比,代码会稍微好理解一些,所以万一面试时实在想不清楚怎么用递归,那就用迭代+栈硬写,所以这种方法我们也是需要会的。

递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
此时大家应该知道我们用栈也可以是实现二叉树的前后中序遍历了。

我们就用迭代法再次练习三道题:144.二叉树的前序遍历 94.二叉树的中序遍历 145.二叉树的后序遍历。

1.迭代法实现前序遍历

我们先看一下前序遍历。
前序遍历是中左右,每次先处理的是中间节点,那么先将跟节点放入栈中,然后将右孩子加入栈,再加 入左孩子。
为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。 不难写出如下代码: (注意代码中空节点不入栈)

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        if (root == null) {
            return res;
        }

        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode node = root;
        while (!stack.isEmpty() || node != null) {
            while (node != null) {
                res.add(node.val);
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            node = node.right;
        }
        return res;
    }
}

此时会发现貌似使用迭代法写出前序遍历并不难,确实不难。

此时是不是想改一点前序遍历代码顺序就把中序遍历搞出来了?

2.迭代法实现中序遍历

如果是中序遍历呢?看这个代码,与上面操作非常相似,但是在很多条件和边界处理又不一样,这里感觉说太多废话没用,建议边调试边自己想一想。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        Deque<TreeNode> stk = new LinkedList<TreeNode>();
        while (root != null || !stk.isEmpty()) {
            while (root != null) {
                stk.push(root);
                root = root.left;
            }
            root = stk.pop();
            res.add(root.val);
            root = root.right;
        }
        return res;
    }
}

3.迭代法实现后序遍历

后续遍历同样要使用栈,这个代码如果自己写可能写不出来,但是如果前面看过我们栈相关文章的读者,这里的代码应该是能看懂的。

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

        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode prev = null;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if (root.right == null || root.right == prev) {
                res.add(root.val);
                prev = root;
                root = null;
            } else {
                stack.push(root);
                root = root.right;
            }
        }
        return res;
    }
}

从这个代码看是不是比递归复杂?但实际比递归好理解。后面很多题目我们会分析递归怎么做,迭代怎么做,但是在面试的时候一般会递归就行了。

以上是关于二叉树6:迭代法实现二叉树的遍历的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的遍历:迭代实现

二叉树的遍历:迭代实现

二叉树(2.二叉树的遍历和实现)

最全二叉树的遍历方式总结

最全二叉树的遍历方式总结

LeetCode JS实现 二叉树(前中后层序)遍历(递归迭代法)