分别用递归和非递归方法求二叉树的三种遍历

二叉树:

前序/中序/后序遍历
前序:根 + 左子树的前序(递归)+ 右子树的前序(递归)
中序: 左子树的中序(递归) + 根 + 右子树的中序(递归)
后序: 左子树的后序(递归)+右子树的后序(递归)+ 根

    //迭代的方法前序遍历
    public static List<Character> preOrder(Node root){
        if (root == null){
            return new ArrayList<>();
        }
        List<Character> list = new ArrayList<>();
        List<Character> leftPreOrder = preOrder(root.left);
        List<Character> rightPreOrder = preOrder(root.right);
        list.add(root.value);
        list.addAll(leftPreOrder);
        list.addAll(rightPreOrder);
        return list;
    }
    //递归:前序遍历
    public static void preOrderTraversal(Node root){
        if (root == null){
            return;
        }
        //根 + 左子树 + 右子树
        System.out.println(root.value);
        preOrderTraversal(root.left);
        preOrderTraversal(root.right);
    }
    //递归:中序遍历
    public static void inOrderTraversal(Node root){
        if (root == null){
            return;
        }
        //左子树 + 根 + 右子树
        inOrderTraversal(root.left);
        System.out.println(root.value);
        inOrderTraversal(root.right);
    }
    //递归:后序遍历
    public static void postOrderTraversal(Node root){
        if (root == null){
            return;
        }
        //左子树 + 右子树 + 根
        postOrderTraversal(root.left);
        postOrderTraversal(root.right);
        System.out.println(root.value);
    }

递归方法的一些诀窍:
1、不要写方法的就做递归展开,站在自己的角度思考,先不用管其他结点
2、找终止条件,在变化的因素中确定,也就是形参
3、找向下的递推公式
4、理解递归方法的调用过程中,会被调用很多次
5、理解调用过程中,局部变量会有多份,只是名字一样

非递归求二叉树前序/中序/后序 遍历
代码:

public static void preorderNoR(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;

        while (!stack.empty() || cur != null) {
            while (cur != null) {
                System.out.println(cur.val);
                stack.push(cur);
                cur = cur.left;
            }

            TreeNode top = stack.pop();
            cur = top.right;
        }
    }

    public static void inorderNoR(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;

        while (!stack.empty() || cur != null) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }

            TreeNode top = stack.pop();
            System.out.println(top.val);
            cur = top.right;
        }
    }
    
    public static void postorderNoR(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        TreeNode last = null;       // 上一个被三次完整经过的结点

        while (!stack.empty() || cur != null) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }

            TreeNode top = stack.peek();
            if (top.right == null || top.right == last) {
                stack.pop();
                System.out.println(top.val);
                last = top;
            } else {
                cur = top.right;
            }
        }
    }

非递归 vs 递归:栈空间更容易控制。
各自的优势:
a、递归使用的栈是系统调用栈,往往空间比较小,而且一般比较固定大小的
b、自己用非递归,手头实现栈,栈的空间在堆上,一般比较大
c、递归写法更简单
以上是我总结出的一些小的技巧,欢迎大家补充。

发布了18 篇原创文章 · 获赞 5 · 访问量 854

猜你喜欢

转载自blog.csdn.net/weixin_44762188/article/details/100087840
今日推荐