二叉树的先,中,后序遍历(递归,非递归)


二叉树的先,中,后序遍历(递归,非递归)

作者:Grey

原文地址:

博客园:二叉树的先,中,后序遍历(递归,非递归)

CSDN:二叉树的先,中,后序遍历(递归,非递归)

说明

本文主要介绍了二叉树的先序,中序,后序遍历。并且分别用如下两种方式实现:

  1. 递归方法
  2. 非递归(使用栈)

示例二叉树

image

数据结构

public static class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

    TreeNode(int val) {
        this.val = val;
    }

    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

先序遍历

先序遍历流程

先头,再左,再右。

示例中的二叉树,先序遍历的结果为:

1-->2-->4-->7-->11-->8-->12-->3-->5-->6-->9-->13-->10

递归方法实现先序遍历

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

    private void pre(TreeNode root, List<Integer> ans) {
        if (root == null) {
            return;
        }
        ans.add(root.val);
        pre(root.left, ans);
        pre(root.right, ans);
    }
}

使用栈实现先序遍历

整个流程是分如下几个步骤:

第一步,申请一个栈,并把头节点压入。

第二步,弹出就收集答案。

第三步,第二步中弹出的节点,如果右孩子不为空,则右孩子入栈。

第四步,第二步中弹出的节点,如果左孩子不为空,则左孩子入栈。

第五步,循环执行第二步到第四步,直到栈为空。

class Solution {
  public List<Integer> preorderTraversal(TreeNode root) {
        if (null == root) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            ans.add(node.val);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        return ans;
    }
}

测评链接:LeetCode 144. Binary Tree Preorder Traversal

中序遍历

中序遍历流程

先中,再左,再右。

示例中的二叉树,中序遍历的结果为:

2-->11-->7-->4-->12-->8-->1-->5-->3-->9-->13-->6-->10

递归方法实现中序遍历

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        in(root, ans);
        return ans;
    }

    private void in(TreeNode root, List<Integer> ans) {
        if (root == null) {
            return;
        }
        in(root.left, ans);
        ans.add(root.val);
        in(root.right, ans);
    }
}

使用栈实现中序遍历

也是申请一个栈,有如下几个步骤:

第一步,整条左边界入栈。

第二步,弹出就收集答案。

第三步,来到右树上执行同第一步的操作。

第四步,直到栈为空。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode cur = root;
        while (!stack.isEmpty() || cur != null) {
            if (cur != null) {
                // 整条左边界入栈
                stack.push(cur);
                cur = cur.left;
            } else {
                TreeNode node = stack.pop();
                // 弹出收集答案
                ans.add(node.val);
                // 来到右树上做同样的操作
                cur = node.right;
            }
        }
        return ans;
    }
}

测评链接:LeetCode 94. Binary Tree Inorder Traversal

后序遍历

后序遍历流程

先左,后右,再中。

示例中的二叉树,后序遍历的结果为:

11-->7-->12-->8-->4-->2-->5-->13-->9-->10-->6-->3-->1

递归方法实现后序遍历

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

    public void post(TreeNode root, List<Integer> ans) {
        if (root == null) {
            return;
        }
        post(root.left, ans);
        post(root.right, ans);
        ans.add(root.val);
    }
}

使用两个栈实现后序遍历

由于我们已经可以通过栈来实现先序遍历,即:先头,再左,再右。

而后序遍历的流程是:先左,再右,再头。

所以我们可以通过先序遍历的代码简单加工得到后序遍历的代码。

首先,我们先通过先序遍历的代码,将先序遍历加工成:先头,再右,再左。

把这个结果放入一个栈中,假设这个栈叫helper, 然后将helper中的内容依次弹出,便是后序遍历的结果。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> helper = new ArrayDeque<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode cur = root;
        stack.push(cur);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            helper.push(node);
            // 先序遍历的时候,是先判断右树,改造一下,先判断左树
            if (node.left != null) {
                cur = node.left;
                stack.push(cur);
            }
            if (node.right != null) {
                cur = node.right;
                stack.push(cur);
            }
        }
        while (!helper.isEmpty()) {
            ans.add(helper.pop().val);
        }
        return ans;
    }
}

测评链接:LeetCode 145. Binary Tree Postorder Traversal

更多

算法和数据结构笔记

参考资料

算法和数据结构体系班-左程云


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM