【遍历二叉树】-前序、中序、后序及层次遍历(java实现)

【遍历二叉树】-前序、中序、后序及层次遍历(java实现)

一、前中后序遍历

  • 前中后序遍历是基于深度遍历(DFS)思想,一般用递归或者栈来实现
package binaryTree;

import java.util.Stack;

/**
 * @Description: 遍历二叉树,前序、中序、后序
 * 每种排序都有两钟实现方式:递归、非递归
 * 非递归:用栈来保存先前走过的路径,以便可以在访问子树后,可以利用栈中的信息,回退到当前节点的双亲节点,进行下一步操作
 * @Author: hw
 * @Date: 2019/8/30 17:50
 */
public class BinaryTreeSelect {
    public static void main(String[] args) {
        //1. 初始化一棵二叉树:[0,1,2,3,4,5,6,7,8,9]
        TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
        for (int i = 0; i <10 ; i++) {
            node[i] = new TreeNode(i);
        }
        for (int i = 0; i <10 ; i++) {
            if (i*2+1<10)
                node[i].left = node[i*2+1];
            if (i*2+2<10)
                node[i].right = node[i*2+2];
        }
        //2. 函数调用
        System.out.println("=========前序================");
        preOrderRe(node[0]);//前序递归
        System.out.println();
        preOrder(node[0]);//前序非递归
        System.out.println();
        System.out.println("=========中序================");
        midOrderRe(node[0]);//中序递归
        System.out.println();
        midOrder(node[0]);//中序非递归
        System.out.println();
        System.out.println("=========后序================");
        postOrderRe(node[0]);//后序递归
        System.out.println();
        //postOrder(node[0]);//后序非递归
        postOrder(node[0]);
    }

    /**
     * 前序:递归
     * @param tree
     */
    public static void preOrderRe(TreeNode tree){
        System.out.print(tree.val);

        TreeNode leftTree = tree.left;
        if (leftTree != null)
            preOrderRe(leftTree);

        TreeNode rightTree = tree.right;
        if (rightTree != null)
            preOrderRe(rightTree);
    }

    /**
     * 前序:非递归
     * @param tree
     */
    public static void preOrder(TreeNode tree){
        Stack<TreeNode> stack = new Stack<>();
        while (tree!=null || !stack.isEmpty()){
            while (tree!=null){
                System.out.print(tree.val);
                stack.push(tree);
                tree = tree.left;
            }
            if (! stack.isEmpty()){
                tree = stack.pop();
                tree = tree.right;
            }
        }
    }

    /**
     * 中序:递归
     * @param tree
     */
    public static void midOrderRe(TreeNode tree){
        if (tree == null)
            return;
        else {
            midOrderRe(tree.left);
            System.out.print(tree.val);
            midOrderRe(tree.right);
        }
    }

    /**
     * 中序:非递归
     * @param tree
     */
    public static void midOrder(TreeNode tree){
        Stack<TreeNode> stack = new Stack<>();
        while (tree != null || !stack.isEmpty()){
            //遍历到最左节点
            while(tree != null){
                stack.push(tree);
                tree = tree.left;
            }
            if (!stack.isEmpty()){
                tree = stack.pop();
                System.out.print(tree.val);
                tree = tree.right;
            }
        }
    }

    /**
     * 后序:递归
     * @param tree
     */
    public static void postOrderRe(TreeNode tree){
        if (tree == null){
            return;
        }
        else{
            postOrderRe(tree.left);
            postOrderRe(tree.right);
            System.out.print(tree.val);
        }
    }

    /**
     * 后序:非递归
     * 利用栈回退时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点
     * 若从左子树回退,则访问右子树;若从右子树回退,则访问根节点
     * 所以需要一个辅助栈,记录压栈时是左子树还是右子树
     * @param tree
     */
    public static void postOrder(TreeNode tree){
        int left =1;//辅助栈里表示左节点
        int right=2;//辅助栈里表示右节点
        Stack<TreeNode> stack = new Stack<>();
        Stack<Integer> stackAssist = new Stack<>();//辅助栈
        while (tree != null || !stack.empty()){
            //将节点压入栈1,并在辅助栈将节点标记为左节点
            while (tree != null){
                stack.push(tree);
                stackAssist.push(left);
                tree=tree.left;
            }
            //如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
            while (!stack.empty() && stackAssist.peek()==right){
                stackAssist.pop();
                System.out.print(stack.pop().val);
            }
            //如果是从左子节点返回父节点,则将标记改为右节点
            if (!stack.empty() && stackAssist.peek()==left){
                stackAssist.pop();
                stackAssist.push(right);
                tree=stack.peek().right;
            }
        }

    }

}
  • 结果:
  • 在这里插入图片描述

二、层次遍历

  • 层次遍历是基于广度优先遍历(BFS)思想,借助队列来实现
public static void levelOrder(TreeNode tree){
        if (tree==null)
            return;

        LinkedList<TreeNode> list = new LinkedList<>();
        list.add(tree);
        TreeNode curNode;
        while (!list.isEmpty()){
            curNode = list.poll();
            System.out.print(curNode.val);
            if (curNode.left != null)
                list.add(curNode.left);
            if (curNode.right != null)
                list.add(curNode.right);
        }
    }
  • 结果:
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值