手撸代码系列(十四)--二叉树的遍历

二叉树的遍历

    本文分别介绍了二叉树的四类遍历情况,分别为前序遍历中序遍历后序遍历层次遍历

分析:
  1. 递归方式前中后序遍历二叉树:递归方式十分简单,代码一看就懂。

  2. 非递归方式实现前中后遍历二叉树:
    2.1. 前序(根左右)
    2.2. 中序(左根右)
    2.3. 后序(左右根)

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class BinTree {
    // 内部类,定义二叉树的结点
    class TreeNode{
        public String val;
        public TreeNode left;
        public TreeNode right;
        // 构造函数,创建一个结点。
        public TreeNode(String val) {
            this.val = val;
            this.left = null;
            this.right = null;
        }
    }
    /**
     * 简易创建一个二叉树
     *          A
     *    B          C
     * D     E    F     G
     *     H        I
     *            J
     * @return
     */
    public  TreeNode creat(){
        TreeNode root = new TreeNode("A");
        TreeNode node2 = new TreeNode("B");
        TreeNode node3 = new TreeNode("C");
        TreeNode node4 = new TreeNode("D");
        TreeNode node5 = new TreeNode("E");
        TreeNode node6 = new TreeNode("F");
        TreeNode node7 = new TreeNode("G");
        TreeNode node8 = new TreeNode("H");
        TreeNode node9 = new TreeNode("I");
        TreeNode node10 = new TreeNode("J");
        root.left = node2;
        root.right = node3;
        node2.left = node4;
        node2.right = node5;
        node3.left = node6;
        node3.right = node7;
        node5.left = node8;
        node6.right = node9;
        node9.left = node10;
        return root;
    }

    // 前序递归遍历二叉树--> 根左右的顺序
    public void preOrder(TreeNode node){
        // 如果所给当前结点为空,直接退出。
        if (node==null){
            return;
        }
        // 访问当前结点
        System.out.print(node.val+" ");
        // 递归调用,访问当前结点的左孩子结点
        preOrder(node.left);
        // 递归调用,访问当前结点的右孩子结点
        preOrder(node.right);
    }

    // 前序非递归遍历二叉树--> 根左右的顺序
    // 递归向非递归的转换,一般是需要借助栈这种数据结构。
    public void noRecPreOrder(TreeNode node){
        // 如果所给当前结点为空,直接退出。
        if (node==null){
            return;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        // 根结点入栈
        stack.push(node);
        /**
         * 套路总结
         * 1. 入栈
         * 2. 出栈
         * 3. 入栈
         * 4. 出栈
         * .....
         * 很明显,该模型按照1-2两步进行循环,但是编程的时候,针对这样的循环操作,
         * 一般将第一步先操作,然后将2,3步作为一个整体进行循环。
         */
        while (!stack.isEmpty()){
            // 出栈
            TreeNode temp = stack.pop();
            // 访问当前结点
            System.out.print(temp.val+" ");
            // 右孩子先入栈,因为要后遍历
            if (temp.right!=null){
                stack.push(temp.right);
            }
            // 左孩子后入栈,因为要先遍历
            if (temp.left!=null){
                stack.push(temp.left);
            }
        }
    }

    // 中序递归遍历二叉树--> 左根右的顺序
    public void midOrder(TreeNode node){
        // 如果所给当前结点为空,直接退出。
        if (node==null){
            return;
        }
        // 递归调用,访问当前结点的左孩子结点
        midOrder(node.left);
        // 访问当前结点
        System.out.print(node.val+" ");
        // 递归调用,访问当前结点的右孩子结点
        midOrder(node.right);
    }


    // 中序非递归遍历二叉树--> 左根右的顺序
    public void noRecMidOrder(TreeNode node){
        // 同样是需要利用栈
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode temp = node;
        // 当栈不为空,或者当前结点不为空
        while (temp!=null || stack.size()>0){
            // 存在左子树
            while (temp!=null){
                stack.push(temp);
                temp = temp.left;
            }
            // 栈非空
            if (!stack.isEmpty()){
                // 出栈
                temp = stack.pop();
                // 访问当前结点
                System.out.print(temp.val+" ");
                temp = temp.right;
            }
        }
    }

    // 后序递归遍历二叉树--> 左右根的顺序
    public void postOrder(TreeNode node){
        if (node==null){
            return;
        }
        // 递归调用,访问当前结点的左孩子结点
        postOrder(node.left);
        // 递归调用,访问当前结点的右孩子结点
        postOrder(node.right);
        // 访问当前结点
        System.out.print(node.val+" ");
    }

    // 后序非递归遍历二叉树--> 左右根的顺序
    public void noRecPostOrder(TreeNode node){
        // 同样是需要利用栈
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode temp = node;
        while (node!=null){
            // 左子树入栈
            for (; node.left!=null; node=node.left) {
                stack.push(node);
            }
            // 当前结点无右子树或者右子树已经输出
            while (node!=null && (node.right==null || node.right== temp)){
                // 访问当前结点
                System.out.print(node.val+" ");
                // 记录上一个已经输出的结点
                temp = node;
                if (stack.empty()){
                    return;
                }
                node = stack.pop();
            }
            // 处理右子树。
            stack.push(node);
            node = node.right;
        }
    }

    // 层次遍历二叉树
    public void levelOrder(TreeNode node){
        // 借助队列
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        /**
         * 添加到队列
         * Queue 中 add() 和 offer()都是用来向队列添加一个元素。
         * 在容量已满的情况下,add() 方法会抛出IllegalStateException异常,offer() 方法只会返回 false 。
         */
        queue.offer(node);
        while (!queue.isEmpty()){   // 当队列非空的时候
            // 从队列中删除第一个元素
            TreeNode root = queue.poll();
            if (root!=null){    // 该结点非空
                // 访问该结点
                System.out.print(root.val+" ");
            }
            // 如果左孩子结点非空,将左孩子结点入队
            if (root.left!=null){
                queue.offer(root.left);
            }
            // 如果右孩子结点非空,将右孩子结点入队
            if (root.right!=null){
                queue.offer(root.right);
            }
        }
    }

    public static void main(String[] args) {
        BinTree binTree = new BinTree();
        TreeNode treeNode = binTree.creat();
        System.out.println("先序递归遍历二叉树");
        binTree.preOrder(treeNode);
        System.out.println("\n--------------------------------");

        System.out.println("先序非递归遍历二叉树");
        binTree.noRecPreOrder(treeNode);
        System.out.println("\n--------------------------------");

        System.out.println("中序递归遍历二叉树");
        binTree.midOrder(treeNode);
        System.out.println("\n--------------------------------");

        System.out.println("中序非递归遍历二叉树");
        binTree.noRecMidOrder(treeNode);
        System.out.println("\n--------------------------------");

        System.out.println("后序递归遍历二叉树");
        binTree.postOrder(treeNode);
        System.out.println("\n--------------------------------");

        System.out.println("后序非递归遍历二叉树");
        binTree.noRecPostOrder(treeNode);
        System.out.println("\n--------------------------------");

        System.out.println("层次遍历二叉树");
        binTree.levelOrder(treeNode);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值