二叉树的前中后顺遍历(递归、栈)Java实现
目录
- 前序遍历
- 中序遍历
- 后续遍历
- 颜色标记法(通用)
- N叉树的前序遍历
- 递归
- 栈-迭代
- 颜色标记法
- 参考链接
前序遍历
力扣144
- 递归
import java.util.ArrayList;
import java.util.List;
public class PreOrder {
public List preOrder(TreeNode root) {
List res = new ArrayList<>();
helper(root, res);
return res;
}
public void helper(TreeNode root, List 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 stackTravers_preorder(TreeNode root) {
List res = new ArrayList<>();
Stack 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;
}
中序遍历
力扣94
- 递归
import java.util.ArrayList;
import java.util.List;
public class PreOrder {
public List inorderTraversal(TreeNode root) {
List res = new ArrayList<>();
helper(root, res);
return res;
}
// recursive
public void helper(TreeNode root, List 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 stackTraversl(TreeNode root) {
List res = new ArrayList<>();
Stack 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;
}
后续遍历
力扣145
- 递归
import java.util.ArrayList;
import java.util.List;
public class PostOrder {
public List postOrderTraversal(TreeNode root) {
List res = new ArrayList<>();
helper(root, res);
return res;
}
// recursive
public void helper(TreeNode root, List 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 stackTravers_postorder(TreeNode root) {
List res = new ArrayList<>();
Stack stack = new Stack<>();
Stack 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;
}
颜色标记法(通用)
颜色标记法
public class ColorMethod {
// 定义含有颜色信息的树节点
class ColorNode{
TreeNode node;
int color;
public ColorNode(TreeNode node, int color) {
this.node = node;
this.color = color;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x;}
}
private final int white = 0;
private final int gray = 1;
public List inorderTraversal(TreeNode root) {
List res = new ArrayList<>();
if (root == null) {
return res;
}
Stack stack = new Stack<>();
stack.push(new ColorNode(root, white));
while (!stack.isEmpty()) {
ColorNode curr = stack.pop();
// 如果此节点没有访问过
if (curr.color == white) {
if (curr.node.right != null) {
stack.push(new ColorNode(curr.node.right, white));
}
// 置为灰色
stack.push(new ColorNode(curr.node, gray));
if (curr.node.left != null) {
stack.push(new ColorNode(curr.node.left, white));
}
} else {
res.add(curr.node.val);
}
}
return res;
}
}
N叉树的前序遍历
力扣 589
递归
/**
* N叉树的前序遍历
*/
public class Recursive {
// 使用递归来前序遍历
public List preorder(Node root) {
List res = new ArrayList<>();
if (root == null) {
return res;
}
helper(root, res);
return res;
}
private void helper(Node curr, List res) {
if (curr != null) {
res.add(curr.val);
for (Node temp : curr.children) {
helper(temp, res);
}
}
}
}
class Node {
public int val;
public List children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List _children) {
val = _val;
children = _children;
}
}
栈-迭代
/**
* 使用栈,采用迭代的方式,来实现多叉树的遍历
*/
public class StackIterator {
public List preorder(Node root) {
// List stack = new LinkedList<>();
Stack stack = new Stack<>();
List res = new LinkedList<>();
if (root == null) {
return res;
}
stack.add(root);
while (!stack.isEmpty()) {
// 前序遍历,因此是root left tight
// 入栈的顺序要反过来
Node curr = stack.pop();
res.add(curr.val);
if (curr.children != null) {
Collections.reverse(curr.children);
for (Node temp : curr.children) {
stack.push(temp);
}
}
}
return res;
}
颜色标记法
public class ColorMethod {
private final int white = 0;
private final int gray = 1;
public List preorder(Node root) {
List res = new LinkedList<>();
if (root == null) {
return res;
}
Stack stack = new Stack<>();
stack.push(new ColorNode(root, white));
while (!stack.isEmpty()) {
ColorNode curr = stack.pop();
if (curr.color == white) {
// 以相反的顺序压栈
if (curr.node.children != null) {
Collections.reverse(curr.node.children);
for (Node temp : curr.node.children) {
stack.push(new ColorNode(temp, white));
}
stack.push(new ColorNode(curr.node, gray));
}
} else {
res.add(curr.node.val);
}
}
return res;
}
}
class Node {
public int val;
public List children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List _children) {
val = _val;
children = _children;
}
}
// 定义含有颜色信息的树节点
class ColorNode{
Node node;
int color;
public ColorNode(Node node, int color) {
this.node = node;
this.color = color;
}
}
参考链接
CSDN
力扣 中序遍历 题解
力扣题解-颜色标记法