数据结构 二叉树的前,中序遍历法(递归与非递归两种实现)

先序遍历:

1.访问根节点

2.先序遍历其左子树

3.先序遍历其右子树

记忆:根左右

例子:


代码实现:

1.首先创建一棵树

 //生成树
    public static TreeNode initTree(){
        TreeNode G = new TreeNode("G", null, null);
        TreeNode H = new TreeNode("H", null, null);
        TreeNode D = new TreeNode("D", G, H);
        TreeNode B = new TreeNode("B", D, null);
        TreeNode I = new TreeNode("I", null, null);
        TreeNode E = new TreeNode("E", null, I);
        TreeNode F = new TreeNode("F", null, null);
        TreeNode C = new TreeNode("C", E, F);
        TreeNode A = new TreeNode("A", B, C);
        return A;
    }

   树的结构如图所示:

2.先序遍历的实现

    //先序遍历:根左右
    // 递归实现
    //但是在数据量大的情况下会出现辅助空间占用过多,占用大量的内存
    public static void preOrderRecursion(TreeNode T) {
        if (T == null) {
            return;
        }
        System.out.print(T.value + " ");
        preOrderRecursion(T.lchild);
        preOrderRecursion(T.rchild);
    }

    /*
    先序遍历的非递归算法
    因为把右边的先存起来,后来倒序读出来,先入后出,和栈一样
    采用栈来实现
    前序遍历有个特点就是遍历到左叶子节点的时候需要回头再去遍历之前未遍历到的右节点
    所以需要先把右边的压入栈中,左边的一直读到左叶子节点再去遍历栈中右边的节点
     */
    public static void preOrderNormal(TreeNode T) {

        //变量用于存储弹出的node
        TreeNode p;
        Stack<TreeNode> stack=new Stack<>();
        stack.push(T) ;   //先把根节点压入栈中
        //当树和栈都不为空时
        while (T!=null&&!stack.isEmpty()){
            p=stack.pop();//弹出栈顶
            System.out.print(p.value+" ");
            //先把右边的压入,因为左边的先读出来
            if (p.rchild!=null){
                stack.push(p.rchild);
            }
            if (p.lchild!=null){
                stack.push(p.lchild);
            }
        }
    }

结果如图:符合先序遍历的规则

总结:

先序遍历的特点就是“根左右”,一直往左读,右边入栈等左边读完再读,比较容易实现


中序遍历:

1.遍历器左子树

2.访问根节点

3.中序遍历其右子树

记忆:左根右

例子:


代码实现:

1.中序遍历的实现

     /*
    中序遍历:左根右
    递归实现
    一直遍历左边,到叶子节点return到父节点,然后右边,递归
     */
    public static void inOrderRecursion(TreeNode T){
        if (T==null){
            return;
        }
        inOrderRecursion(T.lchild);
        System.out.print(T.value + " ");
        inOrderRecursion(T.rchild);
    }

    /*
    中序遍历
    循环实现
    遇到一个节点,压栈,遍历左子树
    左子树遍历完,弹出比那个访问
    然后按照右指针再去中序遍历该节点的右子树
     */
    public static void inOrderNormal(TreeNode T){

        Stack<TreeNode> stack=new Stack<>();
        //用于赋值的局部变量
        TreeNode p=T;
        while (p!=null||!stack.isEmpty()){
            while (p!=null){//当左右子项不为空时
                stack.push(p);//有子树的直接压栈
                p=p.lchild;
            }
            if (!stack.isEmpty()){
                p=stack.pop();//没有左子项就出栈
                System.out.print(p.value+" ");
                p=p.rchild;//访问右子树,若为空则直接弹出父节点

            }
        }
    }

结果:

总结:

右序遍历为“左根右”,所以需要先把根节点压入栈中,遍历其左子树,到叶子节点后,弹出并访问父节点,再看右子树中的元素

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值