java迭代实现二叉树先中后序遍历(非递归)

【README】

本文复习了通过java迭代实现 二叉树先序,中序,后序遍历;

本文引入了 栈,替换了递归,对二叉树进行遍历

补充:使用递归遍历二叉树缺点

  • 众所周知,每次递归,实际是把方法调用帧,连同方法参数一起压入到方法栈; jvm中的方法栈的深度有限,一旦二叉树节点个数过多,可能导致栈溢出的情况
  • 我们通过压入显式栈,替换了递归,即替换了方法栈;在可能的情况下,即便二叉树节点过多,也不会报栈溢出异常;
  • 显式栈,可以用 数组来实现,不一定是 Stack类;

【1】二叉树遍历

【1.1】先序遍历

1)遍历规则

  • 对于一颗二叉树,先遍历其根节点,再遍历左孩子,最后遍历右孩子;
  • 若左孩子下面挂了一棵树(左子树),则继续遍历左子树;
  • 若右孩子下面一棵树(右子树),则继续遍历右子树;

2)先序遍历迭代实现:

/**
     * @description 先序遍历
     * @author xiao tang
     * @date 2022/11/20
     */
    public static void printByPreOrder(MyBinTree root) {
        Stack<MyBinTree> stack = new Stack<>();
        stack.push(root);

        while(!stack.isEmpty()) {
            root = stack.pop();
            if (root == null) {
                System.out.print("NULL ");
            } else {
                System.out.print(root.value + " ");
                stack.push(root.right);
                stack.push(root.left);
            }
        }
    }

// 二叉树 
public class MyBinTree {
    int value;
    MyBinTree left;
    MyBinTree right;
    public MyBinTree(int value) {
        this.value = value ;
    }
}

【1.2】中序遍历

1)遍历规则

  • 对于一颗二叉树,先遍历左孩子,再遍历根节点,最后遍历右孩子;
  • 若左孩子下面挂了一棵树(左子树),则继续遍历左子树;
  • 若右孩子下面一棵树(右子树),则继续遍历右子树;

2)中序遍历迭代实现:

/**
     * @description 中序遍历
     * @author xiao tang
     * @date 2022/11/20
     */
    public static void printByInOrder(MyBinTree root) {
        Stack<MyBinTree> stack = new Stack<>();
        stack.push(root);

        while(!stack.isEmpty()) {
            if (root != null) {
                stack.push(root.left);
                root = root.left;
            } else {
                // 左儿子或右儿子为空
                stack.pop();
                System.out.print("NULL ");
                if (!stack.isEmpty()) {
                    root = stack.pop();
                    System.out.print(root.value + " ");
                    stack.push(root.right);
                    root = root.right;
                }
            }
        }
    }

【1.3】后序遍历

1)遍历规则

  • 对于一颗二叉树,先遍历左孩子,再遍历右孩子,最后遍历根节点;
  • 若左孩子下面挂了一棵树(左子树),则继续遍历左子树;
  • 若右孩子下面一棵树(右子树),则继续遍历右子树;

2)后序遍历迭代实现:

/**
     * @description 后序遍历
     * @author xiao tang
     * @date 2022/11/20
     */
    public static void printByPostOrder(MyBinTree root) {
        Stack<MyBinTree> stack = new Stack<>();
        stack.push(root);
        // 空的右孩子哨兵, 空的左孩子哨兵为null, 以把空右孩子 与 空左孩子 区别开
        MyBinTree rightNullNode = new MyBinTree(0);

        while(!stack.isEmpty()) {
            if (root != null && root != rightNullNode) {
                stack.push(root.left);
                root = root.left;
            } else {
                // 左孩子或右孩子为null
                MyBinTree lastNodeVisited = stack.pop();
                System.out.print("NULL ");
                while (!stack.isEmpty()) {
                    root = stack.peek();
                    MyBinTree rightChild = root.right != null ? root.right : rightNullNode;
                    if (rightChild == lastNodeVisited) {
                        // 若刚刚访问的节点 等于 右孩子,则根节点弹出
                        lastNodeVisited = stack.pop();
                        System.out.print(lastNodeVisited.value + " ");
                    } else {
                        stack.push(rightChild);
                        root = rightChild;
                        break;
                    }
                }
            }
        }
    }

【2】测试案例

1)二叉树结构

 2)测试案例代码:

public static void main(String[] args) {
        MyBinTree head = new MyBinTree(1);

        head.left = new MyBinTree(2);
        head.right = new MyBinTree(3);

        head.left.left = new MyBinTree(4);
        head.left.right = new MyBinTree(5);
        head.right.left = new MyBinTree(6);
        head.right.right = new MyBinTree(7);

        head.left.left.left = new MyBinTree(8);
        head.left.right.right = new MyBinTree(9);
        // 先序打印
        printByPreOrder(head);
        System.out.println();

        // 中序打印
        printByInOrder(head);
        System.out.println();

        // 后序打印
        printByPostOrder(head);
    }

3)打印结果:

先序遍历:1 2 4 8 NULL NULL NULL 5 NULL 9 NULL NULL 3 6 NULL NULL 7 NULL NULL 
中序遍历:NULL 8 NULL 4 NULL 2 NULL 5 NULL 9 NULL 1 NULL 6 NULL 3 NULL 7 NULL 
后序遍历:NULL NULL 8 NULL 4 NULL NULL NULL 9 5 2 NULL NULL 6 NULL NULL 7 3 1

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值