二叉树的前中后序非递归实现:

 非递归的实现需要用到栈结构

1.前序遍历:

分析:前序遍历顺序为 根 -> 左 -> 右

通过先入栈根节点再入栈其右孩子然后在入栈其左孩子就可以控制输出顺序为根 -> 左 -> 右

首先根能排在最前面是因为根出栈打印完才将其右左孩子依次入栈,这就保证了根节点优先于右左孩子输出,二之所以要先入栈右孩子再入栈左孩子正是利用了栈结构的先进后出的特性。由此可知任何一个父节点先于左孩子输出  左孩子先于右孩子输出   而这满足了先序遍历的定义:对于每一颗子树满足输出顺序为根 -> 左 -> 右。

代码流程描述:

1.首先将根节点入栈

2.弹出栈顶的节点   弹出就打印  如果有右孩子将其入栈  如果有左孩子将其入栈

3.重复2过程直至栈空

public void proOrder(Nodes root){
        if (root == null)
            return;
        Stack<Nodes> stack = new Stack<>();//创建栈结构
        stack.push(root);//根节点入栈
        while (!stack.isEmpty()){
            Nodes pop = stack.pop();//弹出节点
            System.out.println(pop);//打印或者进行处理
            if (pop.right != null)
                stack.push(pop.right);
            if (pop.left != null)
                stack.push(pop.left);
        }
}

2.后序遍历:

分析:前序遍历顺序为 左 -> 右 -> 根

如果我们将后序遍历的顺序反过来就是根 -> 右 -> 左了

然后我们再将右左颠倒一下顺序及 根 -> 左 -> 右  这时我们发现了这个顺序不就是前序遍历的顺序了嘛

也就是说我们可以采用前序遍历的思路来求解后序遍历

首先从前序遍历的 根 -> 左 -> 右  变为  右 -> 左 -> 根  这个转换完全可以再用一个栈结构将前序遍历的顺序颠倒过来。

然后从右 -> 左 -> 根  变为  左 -> 右 -> 根   这个转换就更简单了  只需要在将左右孩子压入栈的时候和前序遍历反过来即可。

代码流程描述:

1.创建两个栈  将根节点压入栈1

2.从栈1弹出一个节点  压入栈2  如果从栈1弹出的节点有左孩子就将其压入栈1  如果有右孩子就将其压入栈1

3.重复2过程直至栈1为空

4.一次性将栈2全部弹出来即可

public void postOrders(Nodes root){
        Stack<Nodes> stack1 = new Stack<>();
        Stack<Nodes> stack2 = new Stack<>();
        stack1.push(root);//将根入栈1
        while (!stack1.isEmpty()){
            Nodes pop = stack1.pop();
            stack2.push(pop);//压入栈2
            if (pop.left != null)
                stack1.push(pop.left);
            if (pop.right != null)
                stack1.push(pop.right);
        }
        //一次性将第二个栈的节点全部出栈
        while (!stack2.isEmpty()){
            System.out.println(stack2.pop());
        }
}

中序遍历:

分析: 中序遍历顺序为 左 -> 根 -> 右

由于根节点的输出在左节点之后  所有我们不可能像前序和后序那样通过先压入根再把根弹出压入它的左右孩子的手段实现根输出在左右孩子之前了。

那自然就想到了先先压入左再弹出左 再压入它的根 再压入它的右的想法  但是这个想法其实是不行的 因为无法通过弹出的节点去找到它的父节点

变换一下思路我们先将从根节点出发的左边界全部入栈这样栈里的结构就保证了根先进左孩子后进  这样一会出栈的时候就保证了左孩子先输出其后才是根节点  然后弹出一个节点就看看该节点有没有右孩子 如果有继续将该节点作为根节点的子树的左边界全部压入栈  这样又保证这颗子树左孩子先输出其后才是根节点 而这颗子树的根节点其实是前面一轮的右节点 所有从全局来说实现了先左再根最后右。

代码流程描述:

1.首先从根节点出发 一路将左边界全部压入栈

2.弹出一个节点  打印  如果弹出的节点有右孩子  再以此右孩子作为根节点的子树的左边界全部压入栈

3.重复2直至栈空为止

public void midOrders(Nodes root){
        Stack<Nodes> stack = new Stack<>();
        //首先从根节点出发 一路将左边界全部压入栈
        while (root != null){
            stack.push(root);
            root = root.left;
        }
        while (!stack.isEmpty()){
            Nodes pop = stack.pop();
            System.out.println(pop);
            Nodes temp = pop.right;
            if (temp != null){
                do {
                    stack.push(temp);
                    temp = temp.left;
                }while (temp != null);
            }
        }
}

                
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值