概要:
採用遞歸,狀態標記迭代,普通迭代三種方法實現了二叉樹的前中後序遍歷
狀態標記法的思路來源於題解顏色標記法
其中,遞歸和顏色標記法的前中後序遍歷都非常相似,只需要記憶一個就可以了!
文章目錄
二叉樹的中序遍歷(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;
}
}
二叉樹的層序遍歷
BFS實現
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if (root == null) return new ArrayList<>();
LinkedList<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
queue.offerLast(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> tmpList = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode cur = queue.pollFirst();
tmpList.add(cur.val);
if (cur.left != null) queue.offerLast(cur.left);
if (cur.right != null) queue.offerLast(cur.right);
}
res.add(tmpList);
}
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;
}
}
N叉樹的層序遍歷
BFS實現
public class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new LinkedList<>();
if (root == null) return res;//root爲空特殊情況
Deque<Node> deque = new LinkedList<Node>();
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
//每一層臨時集合
List<Integer> tmpList = new LinkedList<>();
for (int i = 0; i < size; i++) {
Node cur = deque.poll();
tmpList.add(cur.val);
for (Node node : cur.children) {
if (node != null)//剪枝
deque.offer(node);
}
}
res.add(tmpList);
}
return res;
}
}