概要:
采用递归,状态标记迭代,普通迭代三种方法实现了二叉树的前中后序遍历
状态标记法的思路来源于题解颜色标记法
其中,递归和颜色标记法的前中后序遍历都非常相似,只需要记忆一个就可以了!
文章目录
二叉树的中序遍历(3种实现)
递归实现
public class Solution {
List<Integer> res;
public List<Integer> inorderTraversal(TreeNode root) {
res = new ArrayList<>();
helper(root);
return res;
}
private void helper(TreeNode root) {
if (root == null) return;
helper(root.left);
res.add(root.val);
helper(root.right);
}
}
状态标记法迭代实现
public class Solution {
//加强的node类,加上了node是否被遍历过了的标记
class IncreaseNode {
TreeNode node;
boolean is_finish;//是否已经遍历过了
public IncreaseNode(TreeNode node, boolean is_finish) {
this.node = node;
this.is_finish = is_finish;
}
}
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<IncreaseNode> stack = new Stack<>();
stack.push(new IncreaseNode(root, false));
while (!stack.isEmpty()) {
IncreaseNode inode = stack.pop();
if (!inode.is_finish) {
//注意: 压栈顺序和排序方式是相反的
if (inode.node.right != null) stack.push(new IncreaseNode(inode.node.right, false));
stack.push(new IncreaseNode(inode.node, true));
if (inode.node.left != null) stack.push(new IncreaseNode(inode.node.left, false));
} else {
res.add(inode.node.val);
}
}
return res;
}
}
普通迭代实现
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
//存在左节点,就一直压栈
while (cur!=null){
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
return res;
}
}
二叉树的前序遍历(3种实现)
递归实现
class Solution {
List<Integer> res;
public List<Integer> preorderTraversal(TreeNode root) {
res = new ArrayList<>();
helper(root);
return res;
}
private void helper(TreeNode root) {
if (root == null) return;
res.add(root.val);
helper(root.left);
helper(root.right);
}
}
状态标记法迭代实现
public class Solution {
//加强的node类,加上了node是否被遍历过了的标记
class IncreaseNode {
TreeNode node;
boolean is_finish;//是否已经遍历过了
public IncreaseNode(TreeNode node, boolean is_finish) {
this.node = node;
this.is_finish = is_finish;
}
}
public List<Integer> preorderTraversal(TreeNode root) {
if (root==null)return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<IncreaseNode> stack = new Stack<>();
stack.push(new IncreaseNode(root, false));
while (!stack.isEmpty()) {
IncreaseNode cur = stack.pop();
if (!cur.is_finish){
if (cur.node.right!=null)stack.push(new IncreaseNode(cur.node.right,false));
if (cur.node.left!=null)stack.push(new IncreaseNode(cur.node.left,false));
stack.push(new IncreaseNode(cur.node,true));
}else {
res.add(cur.node.val);
}
}
return res;
}
}
普通迭代实现
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
if (cur == null) {
continue;
}
res.add(cur.val);
stack.push(cur.right);
stack.push(cur.left);
}
return res;
}
}
二叉树的后序遍历(3种实现)
递归实现
class Solution {
List<Integer> res;
public List<Integer> postorderTraversal(TreeNode root) {
res = new ArrayList<>();
helper(root);
return res;
}
private void helper(TreeNode root) {
if (root == null)return;
helper(root.left);
helper(root.right);
res.add(root.val);
}
}
状态标记法迭代实现
class Solution {
//加强的node类,加上了node是否被遍历过了的标记
class IncreaseNode {
TreeNode node;
boolean is_finish;
public IncreaseNode(TreeNode node, boolean is_finish) {
this.node = node;
this.is_finish = is_finish;//是否已经遍历过了
}
}
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<IncreaseNode> stack = new Stack<>();
stack.push(new IncreaseNode(root, false));
while (!stack.isEmpty()) {
IncreaseNode cur = stack.pop();
if (!cur.is_finish) {
stack.push(new IncreaseNode(cur.node, true));
if (cur.node.right != null) stack.push(new IncreaseNode(cur.node.right, false));
if (cur.node.left != null) stack.push(new IncreaseNode(cur.node.left, false));
} else {
res.add(cur.node.val);
}
}
return res;
}
}
普通迭代实现
后序遍历的普通迭代太难想了,所以采用取巧的方式实现
我们能很容易写出来的是前序遍历的普通迭代
前序遍历是:根-左-右
后序遍历是:左-右-根
左右在里面都是等价的,所以我们把前序的left和right对换一下,然后将结果逆序,就是左-右-根
了
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
if (cur == null) {
continue;
}
res.add(cur.val);
stack.push(cur.left);
stack.push(cur.right);
}
Collections.reverse(res);
return res;
}
}
或者
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
LinkedList<Integer> res = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
if (cur == null) {
continue;
}
res.addFirst(cur.val);
stack.push(cur.left);
stack.push(cur.right);
}
return res;
}
}
N叉树的前序遍历
递归实现
public class Solution {
List<Integer> res;
public List<Integer> preorder(Node root) {
res = new ArrayList<>();
helper(root);
return res;
}
private void helper(Node root) {
if (root == null) return;
res.add(root.val);
for (Node node : root.children) {
helper(node);
}
}
}
迭代实现
class Solution {
public List<Integer> preorder(Node root) {
if (root == null) return new ArrayList<>();
Stack<Node> stack = new Stack<Node>();
List<Integer> res = new ArrayList<>();
stack.push(root);
while (!stack.isEmpty()) {
Node cur = stack.pop();
res.add(cur.val);
for (int i = cur.children.size() - 1; i >= 0; i--) {
if (cur.children.get(i)!=null){
stack.push(cur.children.get(i));
}
}
}
return res;
}
}
N叉树的后序遍历
递归实现
public class Solution {
List<Integer> res;
public List<Integer> postorder(Node root) {
res = new ArrayList<>();
helper(root);
return res;
}
private void helper(Node root) {
if (root == null) return;
for (Node node : root.children) {
helper(node);
}
res.add(root.val);
}
}
迭代实现
public class Solution {
public List<Integer> postorder(Node root) {
if (root == null) return new ArrayList<>();
Stack<Node> stack = new Stack<Node>();
LinkedList<Integer> res = new LinkedList<>();
stack.push(root);
while (!stack.isEmpty()) {
Node cur = stack.pop();
res.addFirst(cur.val);
//为什么从左往右压栈:addFirst从右侧开始加,最终是左右根,加完了根就先右
for (int i = 0; i < cur.children.size(); i++) {
if (cur.children.get(i) != null) {
stack.push(cur.children.get(i));
}
}
}
return res;
}
}