思路:
1. 准备一个栈, 把根节点入栈
2. 循环取栈顶元素, 并且访问
3. 判断当前节点的右子树是否为空, 非空就入栈
4. 判断当前节点的左子树是否为空, 非空就入栈
循环操作2, 3, 4
代码实现:
public static void preOrderByLoop(TreeNode root) {
// 借助栈来辅助
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode top = stack.pop();
// 访问这个节点
System.out.print(top.val + " ");
// 先将右子树入栈, 再将左子树入栈, 因为栈后进先出, 先序遍历顺序是根左右, 要先访问左子树
while (top.left != null) {
stack.push(root.left);
}
while (top.right != null) {
stack.push(root.right);
}
}
}
思路:
1. 从 root 出发一直向左找, 直到左子树为 null
2. 取栈顶元素, 出栈并且访问这个元素
3. 把刚才栈顶元素的右子树作为起点, 继续往左找, 遇到的元素依次入栈.
4. 重复 2, 3步
代码实现:
public static void inOrderByLoon(TreeNode root) {
if (root == null) {
return;
}
// 借助栈来操作
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (true) {
// 1. 循环一直找左子树, 把遇到的所有的左子树都入栈
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
// 2. 如果当前栈为空, 遍历结束
if (cur == null) {
break;
}
// 3. 获取栈顶元素并访问
TreeNode top = stack.pop();
System.out.print(top.val + " ");
/// 4. 从当前节点的右子树出发, 继续刚才的过程
cur = top.right;
}
}
思路:
4. 创建一个 cur 变量, 指向 root
从 cur 出发循环向左找, 只要非空, 都入栈
2. 获取栈顶元素(peek()), 判断栈顶元素能不能被访问
(1) 如果栈顶元素没有右子树, 说明该节点可以被访问
(2) 如果栈顶元素的右子树已经被访问过了(看看上一个被访问的元素是不是他的右子树), 该节点也可以被访问
3. 从刚才栈顶元素的右子树开始, 继续执行这个过程
代码实现:
public static void postOrderByLoop(TreeNode root) {
if (root == null) {
return;
}
// 创建一个栈来辅助
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode prev = null;
// prev 用来记录已经访问过的节点中的最后一个节点(即将被访问元素的前一个节点)
while (true) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
if (stack.isEmpty()) {
break;
}
// 拿出栈顶元素的值, 看他能不能被访问
TreeNode top = stack.peek();
if (top.right == null || top.right == prev) {
// 此时说明这个栈顶元素是可以访问的
System.out.print(top.val + " ");
stack.pop();
prev = top;
// 更新 prev 的值, 让他时刻指向已经访问的最后一个元素
} else {
cur = top.right;
}
}
}