二叉树的先,中,后序遍历(递归,非递归)
作者:Grey
原文地址:
说明
本文主要介绍了二叉树的先序,中序,后序遍历。并且分别用如下两种方式实现:
-
递归方法
-
非递归(使用栈)
示例二叉树
数据结构
public 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
递归方法实现先序遍历
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
pre(root, ans);
return ans;
}
public void pre(TreeNode root, List<Integer> ans) {
if (root == null) {
return;
}
ans.add(root.val);
pre(root.left, ans);
pre(root.right, ans);
}
使用栈实现先序遍历
流程如下:
第一步,申请一个栈,并把头节点压入;
第二步,弹出就收集答案;
第三步,第二步中弹出的节点,如果右孩子不为空,则右孩子入栈;
第四步,第二步中弹出的节点,如果左孩子不为空,则左孩子入栈;
第五步,循环执行第二步到第四步,直到栈为空。
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if (null == root) {
return ans;
}
Stack<TreeNode> stack = new Stack<>();
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
递归方法实现中序遍历
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);
}
使用栈实现中序遍历
也是申请一个栈,有如下几个步骤:
第一步,整条左边界入栈。
第二步,弹出就收集答案。
第三步,来到右树上执行同第一步的操作。
第四步,直到栈为空。
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
if (null == root) {
return ans;
}
Stack<TreeNode> stack = new Stack<>();
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
递归方法实现后序遍历
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return new ArrayList<>();
}
List<Integer> ans = new ArrayList<>();
pos(root, ans);
return ans;
}
public void pos(TreeNode root, List<Integer> ans) {
if (root == null) {
return;
}
pos(root.left, ans);
pos(root.right, ans);
ans.add(root.val);
}
使用两个栈实现后序遍历
由于我们已经可以通过栈来实现先序遍历,即:先头,再左,再右。
而后序遍历的流程是:先左,再右,再头。
所以我们可以通过先序遍历的代码简单加工得到后序遍历的代码。
首先,我们先通过先序遍历的代码,将先序遍历加工成:先头,再右,再左。
把这个结果放入一个栈中,然后将这个栈中的内容依次弹出,便是后序遍历的结果。
public List<Integer> postorderTraversal2(TreeNode root) {
if (root == null) {
return new ArrayList<>();
}
List<Integer> ans = new ArrayList<>();
Stack<TreeNode> helper = new Stack<>();
Stack<TreeNode> stack = new Stack<>();
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