• 算法笔记-二叉树前序,中序,后序


      二叉树遍历如下图所示,前序遍历对于1(父),3(左),5(右)这三个节点来说则先1后3,最后5,同理3,4,2这三个也是先父再左再右,那么对于下图来说,前序遍历顺序为1,3,4,5,6,2,7,5,以此类推:

        先序遍历:先父,再左,最后右,

        中序遍历:先左,再父,最后右

        后序遍历:先左,再右,最后父

       我们先看递归版的前序遍历:

    /**
         * 前序遍历
         * @param head
         */
        public static void preOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            System.out.print(head.value + " ");
            preOrderRecur(head.left);
            preOrderRecur(head.right);
        }

    代码非常简单,就是进来直接打印,然后先递归左子树,后递归右子树

    /**
         * 中序遍历
         * @param head
         */
        public static void inOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            inOrderRecur(head.left);
            System.out.print(head.value + " ");
            inOrderRecur(head.right);
        }

    先递归左子树,然后打印,后递归右子树,相信看到这里,应该知道后序遍历咋写了“

    /**
         * 后续遍历
         * @param head
         */
        public static void posOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            posOrderRecur(head.left);
            posOrderRecur(head.right);
            System.out.print(head.value + " ");
        }

    递归版的可以说是非常简单了,我们再来看下非递归版本怎么实现的:

    /**
         * 前序遍历(非递归版)
         * @param head
         */
        public static void preOrderUnRecur(Node head) {
            if(head != null){
                Stack<Node> stack = new Stack<>();
                stack.push(head);
                while(!stack.isEmpty()){
                    Node pop = stack.pop();
                    System.out.print(pop.value+ " ");
                    if(pop.right != null){
                        stack.push(pop.right);
                    }
                    if(pop.left != null){
                        stack.push(pop.left);
                    }
                }
                System.out.println();
            }
        }

    这里使用栈来存储节点,思想是循环先放入右节点,然后放入左节点,循环取出栈顶,这样可以每次循环先取出左节点,并且在打印时将左节点的右子节点放在当前节点的右节点上层,刚好满足我们的前序遍历,

    再看中序遍历:

    /**
         * 中序遍历
         * @param head
         */
        public static void inOrderUnRecur(Node head) {
            if(head != null) {
                Stack<Node> stack = new Stack<>();
                while(!stack.empty() || head != null){
                    if(head != null){
                        stack.push(head);
                        head = head.left;
                    }else{
                        head = stack.pop();
                        System.out.print(head.value + " ");
                        head = head.right;
                    }
                }
                System.out.println();
            }
        }

    中序遍历非递归版本的思想:先将当前节点下所有非空左子节点塞入栈,出栈时打印并将右子节点放入栈,下一次循环打印,,则可以实现左,父,右的顺序打印。

    后序遍历的难度稍微大点,因为我们前面打印的节点都是有直接关联的,比如左-父-右,这些都可以通过入栈出栈完成,而后序遍历为左-右-父,左右节点是没有直接联系的,所以我们没法通过出入栈去退栈打印,因此我们只能想其他办法去实现,比如:先序遍历的顺序为父-左-右,我们也可以改造一下变为父-右-左,反向打印不就是左-右-父了吗,说干就干:

    /**
         * 后序遍历
         * @param head
         */
        public static void posOrderUnRecur(Node head) {
            System.out.print("pos-order: ");
            if(head != null){
                Stack<Node> stack = new Stack<>();
                Stack<Node> stack1 = new Stack<>();
                stack.push(head);
                while(!stack.isEmpty()){
                    Node pop = stack.pop();
                    stack1.push(pop);
                    if(pop.left != null){
                        stack.push(pop.left);
                    }
                    if(pop.right != null){
                        stack.push(pop.right);
                    }
                }
                while(!stack1.empty()){
                    System.out.print(stack1.pop().value + " ");
                }
            }
            System.out.println();
        }

    这里我们对前序遍历进行了改造:将先入右再入左改为先入左再入右实现父-右-左的逆前序遍历,再将之前打印时改为入;另外一个栈,全部结束后出栈打印则可实现左-右-父的后序非递归打印,堪称完美。

  • 相关阅读:
    取多列数据的最大值、最小值sql
    java中实现时间差的计算
    数据更新sql
    自连接的用法sql
    获取第一条,最后一条数据sql
    复制表结构 表数据sql
    用 ORDER BY 生成“排序”列sql
    表之间的数据匹配(生成交叉表)sql
    SIP呼叫流程
    如何在WindowsPhone Bing Map控件中显示必应中国中文地图、谷歌中国中文地图。
  • 原文地址:https://www.cnblogs.com/gmt-hao/p/14928803.html
Copyright © 2020-2023  润新知