二叉树的前中后顺遍历(递归、栈)Java实现
前序遍历
- 递归
import java.util.ArrayList;
import java.util.List;
public class PreOrder {
public List<Integer> preOrder(TreeNode root) {
List<Integer> res = new ArrayList<>();
helper(root, res);
return res;
}
public void helper(TreeNode root, List<Integer> res) {
if (root != null) {
res.add(root.val);
if (root.left != null) {
helper(root.left, res);
}
if (root.right != null) {
helper(root.right, res);
}
}
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x;}
}
- 栈
public List<Integer> stackTravers_preorder(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
res.add(curr.val);
stack.push(curr);
curr = curr.left;
}
if (!stack.isEmpty()) {
curr = stack.pop();
curr = curr.right;
}
}
return res;
}
中序遍历
- 递归
import java.util.ArrayList;
import java.util.List;
public class PreOrder {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
helper(root, res);
return res;
}
// recursive
public void helper(TreeNode root, List<Integer> res) {
if (root != null) {
if (root.left != null) {
helper(root.left, res);
}
res.add(root.val);
if (root.right != null) {
helper(root.right, res);
}
}
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x;}
}
- 栈
public List<Integer> stackTraversl(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
// push the left tree into stack
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
// when reached leaf node
curr = stack.pop();
res.add(curr.val);
curr = curr.right;
}
return res;
}
后续遍历
- 递归
import java.util.ArrayList;
import java.util.List;
public class PostOrder {
public List<Integer> postOrderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
helper(root, res);
return res;
}
// recursive
public void helper(TreeNode root, List<Integer> res) {
if (root != null) {
if (root.left != null) {
helper(root.left, res);
}
if (root.right != null) {
helper(root.right, res);
}
res.add(root.val);
}
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x;}
}
- 栈
算法核心思想:
首先要搞清楚先序、中序、后序的非递归算法共同之处:用栈来保存先前走过的路径,以便可以在访问完子树后,可以利用栈中的信息,回退到当前节点的双亲节点,进行下一步操作。
后序遍历的非递归算法是三种顺序中最复杂的,原因在于,后序遍历是先访问左、右子树,再访问根节点,而在非递归算法中,利用栈回退到时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点,如果从左子树回退到根节点,此时就应该去访问右子树,而如果从右子树回退到根节点,此时就应该访问根节点。所以相比前序和后序,必须得在压栈时添加信息,以便在退栈时可以知道是从左子树返回,还是从右子树返回进而决定下一步的操作。
————————————————
版权声明:本文为CSDN博主「coder__666」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/coder__666/article/details/80349039
public List<Integer> stackTravers_postorder(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
Stack<Integer> stack2 = new Stack<>(); // 辅助栈,用于保存,压入栈的是左子树还是右子树
TreeNode curr = root;
int left = 1; // note left tree
int right = 2; // note right tree
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
stack2.push(left);
curr = curr.left;
}
while (!stack.isEmpty() && stack2.peek() == right) {
// 如果是从左子节点返回父节点,则任务完成,将两个栈的栈顶弹出,记录结果
stack2.pop();
res.add(stack.pop().val);
}
if (!stack.isEmpty() && stack2.peek() == left) {
// 如果是从左子树返回,则先将辅助栈弹出栈顶,下一个应该压栈的是右子树
//
stack2.pop();
stack2.push(right);
curr = stack.peek().right;
}
}
return res;
}