144. 二叉树的前序遍历
递归遍历:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
pre(root, res);
return res;
}
private void pre(TreeNode node, List<Integer> res){
if(node == null)return;
res.add(node.val);
pre(node.left, res);
pre(node.right, res);
}
}
迭代遍历:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stk = new Stack<>();
List<Integer> res = new ArrayList<>();
if(root == null){
return res;
}
stk.push(root);
while(!stk.isEmpty()){
// 每次都是先处理“中”,前序遍历顺序为中-左-右,所以压入栈的顺序要中-右-左,然后中先被处理,然后按左-右的顺序出栈
TreeNode node = stk.pop();
res.add(node.val);
if(node.right != null)stk.push(node.right);
if(node.left != null)stk.push(node.left);
}
return res;
}
}
94. 二叉树的中序遍历
递归遍历:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
in(root, res);
return res;
}
private void in(TreeNode node, List<Integer> res){
if(node == null)return;
in(node.left, res);
res.add(node.val);
in(node.right, res);
}
}
迭代遍历:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stk = new Stack<>();
List<Integer> res = new ArrayList<>();
if(root == null)return res;
while(root != null || !stk.isEmpty()){
if(root != null){
stk.push(root);
root = root.left;
}
else{
root = stk.pop();
res.add(root.val);
root = root.right;
}
}
return res;
}
}
145. 二叉树的后序遍历
递归遍历:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
post(root, res);
return res;
}
private void post(TreeNode node, List<Integer> res){
if(node == null)return;
post(node.left, res);
post(node.right, res);
res.add(node.val);
}
}
迭代遍历:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
// 后序遍历顺序 左-右-中 入栈顺序:中-左-右 出栈顺序:中-右-左,最后翻转结果
Stack<TreeNode> stk = new Stack<>();
List<Integer> res = new ArrayList<>();
if(root == null){
return res;
}
stk.push(root);
while(!stk.isEmpty()){
TreeNode node = stk.pop();
res.add(node.val);
if(node.left != null)stk.push(node.left);
if(node.right != null)stk.push(node.right);
}
Collections.reverse(res); // Collections.reverse()对列表进行原地修改并且返回void
return res;
}
}
迭代的统一写法
以中序遍历为例
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<Integer> stack = new Stack<>();
if(root != null)stack.push(root); // 先压入根节点
while(!stack.isEmpty()){
TreeNode node = stack.peek();
if(node != null){
stack.pop(); // 先将该节点弹出避免重复操作
// 以下就是核心部分
// 中序遍历顺序是左根右,所以压栈就是右根左
if(node.right != null)stack.push(node.right);
stack.push(node);
stack.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if(node.left != null)stack.push(node.left);
}
else {// 只有遇到空节点的时候,才将下一个节点放进结果集
stack.pop(); // 弹出空节点
node = stack.pop(); // 重新取出栈中元素
res.add(node.val);
}
}
return res;
}
}
将上述代码适用于不同的遍历顺序时,只需要按照相应的顺序压栈即可。