非递归实现二叉树的三种遍历

  1. 先序遍历

思路:

     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. 中序遍历

思路:
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;
        }
    }
  1. 后序遍历

思路:
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;
            }
        }
    }

你可能感兴趣的:(非递归实现二叉树的三种遍历)