树结构:
//Definition for a binary tree node.
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.递归方法
- 首先遍历左子树
- 再遍历当前结点
- 最后遍历右子树
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
process(root,list);
return list;
}
public void process(TreeNode root,List<Integer> list){
if(root==null) return;
process(root.left,list);
list.add(root.val);
process(root.right,list);
}
}
2.非递归法
需要一个辅助栈
- 若当前结点不为空,则把当前的节点的所有左孩子加入栈中
- 若当前结点为空,说明遇到了叶子结点,从栈中弹出一个结点,对这个结点的右孩子做相同的操作
- 重复上述操作直到栈为空且当前结点为空。
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
List<Integer> ans = new ArrayList<>();
if(root==null) return ans;
stack.push(root);
root = root.left;
while(!stack.isEmpty()||root!=null){
if(root!=null){
stack.push(root);
root = root.left;
}else{
root = stack.pop();
ans.add(root.val);
root = root.right;
}
}
return ans;
}
二、先序遍历
1.递归方法
- 首先遍历当前结点
- 然后遍历左子树
- 最后遍历右子树
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
process(root,list);
return list;
}
public void process(TreeNode root,List<Integer> list){
if(root==null) return;
list.add(root.val);
process(root.left,list);
process(root.right,list);
}
}
2.非递归方法
需要一个辅助栈,首先把头结点放进栈中
- 每次从栈中弹出一个结点cur
- 操作cur
- 先把cur右孩子压入栈中,再把cur左孩子压入栈中(若存在的话)
- 重复以上步骤直到栈为空
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
List<Integer> ans = new ArrayList<>();
if(root==null) return ans;
stack.push(root);
while(!stack.isEmpty()){
root = stack.pop();
ans.add(root.val);
if(root.right!=null) stack.push(root.right);
if(root.left!=null) stack.push(root.left);
}
return ans;
}
}
数学理解:
每次循环先处理当前结点,并且把他的右孩子,左孩子依次入栈,出栈的时候就能保证这三个结点一定有中 左 右的顺序,推广到整颗书上的所有结点都会具有这样的关系,因此就保证了先序遍历。
三、后序遍历
1.递归方法
- 首先遍历左子树
- 然后遍历右子树
- 最后遍历当前结点
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
process(root,ans);
return ans;
}
public void process(TreeNode root,List<Integer> list){
if(root==null) return;
process(root.left,list);
process(root.right,list);
list.add(root.val);
}
}
2.非递归法
根据之前的先序遍历,我们只需要改变左右孩子的入栈顺序,就能将中 左 右的顺序改成中 右 左,最后再反向遍历中 右 左就可以得到正确的后续遍历。
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
Stack<Integer> s = new Stack<>();
List<Integer> ans = new ArrayList<>();
if(root==null) return ans;
stack.push(root);
while(!stack.isEmpty()){
root = stack.pop();
s.push(root.val);
if(root.left!=null) stack.push(root.left);
if(root.right!=null) stack.push(root.right);
}
while(!s.isEmpty()){
ans.add(s.pop());
}
return ans;
}
}