非递归遍历,都是用栈实现,本质上都是用栈的进出来模仿递归行为,任何递归解法都可以转换成栈来解决。
1、先序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
if (root != null) {
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;
}
}
中序遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || root != null){
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
ans.add(root.val);
root = root.right;
}
return ans;
}
}
后续遍历解法一:
用两个栈实现,这种方法是建立在前序遍历代码的基础上(前序遍历是中->左->右,稍微改动代码,将这个顺序改成中->右->左,然后建立一个新栈,将所有节点push到这个新栈中,这样从这个新栈中弹出来的顺序就是左->右->中,即为后序遍历!)
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
Stack<TreeNode> stack_ans = new Stack<>();
List<Integer> ans = new ArrayList<>();
if (root != null) {
stack.push(root);
while(!stack.isEmpty()) {
root = stack.pop();
stack_ans.push(root);
if (root.left != null) {
stack.push(root.left);
}
if (root.right != null) {
stack.push(root.right);
}
}
}
while (!stack_ans.isEmpty()) {
ans.add(stack_ans.pop().val);
}
return ans;
}
}
后续遍历解法2
用一个栈实现,对比后序遍历解法1,只用到一个栈,空间复杂度较好。
class Solution {
public List<Integer> postorderTraversal(TreeNode h) {
List<Integer> ans = new ArrayList<>();
if (h != null) {
Stack<TreeNode> stack = new Stack<>();
stack.push(h);
// 如果始终没有打印过节点,h就一直是头节点
// 一旦打印过节点,h就变成打印节点
// 之后h的含义 : 上一次打印的节点
while (!stack.isEmpty()) {
TreeNode cur = stack.peek();
if (cur.left != null && cur.left != h && cur.right!=h) {
stack.push(cur.left);
} else if(cur.right != null && cur.right != h) {
stack.push(cur.right);
} else {
ans.add(cur.val);
h = stack.pop();
}
}
}
return ans;
}
}