用迭代的方法来做的思路是:
- 谁后读取,谁就先入栈,以此把三个节点入栈。三个节点中的头结点入栈之后,还要加入一个null作为空指针标记,以便下次弹出的时候直接读取。
- 每次新一轮循环,把最先读取的那个node弹出作为头,然后重复第一步的操作
我用图模拟了一下:
前序遍历:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stk = new Stack<>();
if(root == null) return res;
stk.push(root);
while(!stk.isEmpty()){
TreeNode node;//更新为遍历到的节点
node = stk.pop();
if(node != null){
//出栈
//按照右左中的次序假如到栈里
//若选中节点未处理,需要在压入栈之后,加入一个空指针作为标记
if(node.right != null) stk.push(node.right);
if(node.left != null) stk.push(node.left);
stk.push(node);
stk.push(null);
}
else{
node = stk.pop();
res.add(node.val);
}
}
return res;
}
}
中序遍历:
while(!stk.isEmpty()){
TreeNode node;//更新为遍历到的节点,入栈顺序为右中左,所以肯定先弹出左节点为新一次循环
node = stk.pop();
if(node != null){
//按照右中左的次序假如到栈里
//若选中节点未处理,需要在压入栈之后,加入一个空指针作为标记
if(node.right != null) stk.push(node.right);
stk.push(node);
stk.push(null);
if(node.left != null) stk.push(node.left);
}
else{
node = stk.pop();
res.add(node.val);
}
}
后序遍历:
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stk = new Stack<>();
if(root == null) return res;
stk.push(root);
while(!stk.isEmpty()){
TreeNode node;//更新为遍历到的节点,入栈顺序为中右左,所以肯定先弹出左节点为新一次循环
node = stk.pop();
if(node != null){
//按照中右左的次序假如到栈里
//若选中节点未处理,需要在压入栈之后,加入一个空指针作为标记
stk.push(node);
stk.push(null);
if(node.right != null) stk.push(node.right);
if(node.left != null) stk.push(node.left);
}
else{
node = stk.pop();
res.add(node.val);
}
}
return res;