创建二叉树的方式,目前掌握的三种:

1、从先序

2、从层序

3、从先序+中序【LeetCode,剑指Offer07】

 

一、 思路

1、从先序创建二叉树

/**

     * 从先序建立二叉树,0表示停止延伸。停止延伸时,叶子节点后面要有2个0才算停止延伸。

     * 例1:

     *     1

     *   2   3

     * 4    5

     * 先序为,1 2 4 0 0 0 3 5 0 0 0

     *

     * 例2:

     *     1

     *   2   3

     *    4 5

     * 先序为,1 2 0 4 0 0 3 5 0 0 0

     *

     * 中序为,0 2 4 1 5 3 0 ?这个可以搞定吗?感觉搞不定,你上来就空,让人怎么接?

     *

     * 后序为,0 4 2 5 0 3 1 ?这个呢?

     *

     */

 

2、从层序创建二叉树

 /**

     * 从层序创建二叉树,用的是下标。【不知道有没有递归的方法???】

     *

     *

     * 从层序创建二叉树,0表示为空,以#结束。与上面的停止延伸还有所不同,叶子节点不用输入2个0。

     *

     * 例子:

     *     1

     *   2   3

     * 4    5

     * 层序为,1 2 3 4 0 5 0

     *

     *

     * 问题:

     *  1、传入的root没有用到,而是新建的root,返回的也是新建的root。如果必须要用到传入root的话,0要单独处理!

     *  2、log是以e为底的对数,如果以2为底,得除以log(2)。应该是(Math.log(n + 1) / Math.log(2)),而非 Math.log(n + 1)。

     *  3、求2的幂次方,应该用Math.pow(2, i),不能用2^i。2^0是2,因为^是异或符号,不是多少次方!!!

     *

     *

     * 【不行了,脑子不够用了,撤吧,明天再搞!!!-1:53】

     * 全部搞定了,开干,2021-8-1 22:01:09

     * 终于OK啦!2021-8-2 03:13:01

     *

     */

 

 

3、从先序+中序 创建二叉树

之前做的,忘了。【有空再做一遍,字节面试中问过】

 

 

只记得:

前提:无重复节点。

1、先序的第一个是root。

2、在中序中查到root位置。中序的root左边是左子树,中序的root右边是右子树。

3、 先序的第二个开始是左子树,长度由2可知。剩下的就是右子树。

4、3中,先序左子树第一个节点即左子树的根就是root的左孩子,右子树的第一个节点即右子树的根就是root的右孩子。

 

 

二、代码+输出【完整】

包括代码:

二叉树父子关系+推导》和《二叉树四种遍历:前序、中序、后序、层序。方法:递归、迭代、Morris

 

1、代码

package 数据结构.树;

import java.util.*;
import java.util.stream.Collectors;

public class TestTree {
    public static void main(String[] args) {
        //      * 例1:
        //      *     1
        //      *   2   3
        //      * 4    5
        //      * 先序为,1 2 4 0 0 0 3 5 0 0 0
        //        层序为,1 2 3 4 0 5 0
        //      *
        //      * 例2:
        //      *     1
        //      *   2   3
        //      *    4 5
        //      * 先序为,1 2 0 4 0 0 3 5 0 0 0
        //        层序为,1 2 3 0 4 5 0

        //1 2 4 0 0 0 3 5 0 0 0 #
        //1 2 0 4 0 0 3 5 0 0 0 #

        //控制台输入Queue:
        // Scanner in = new Scanner(System.in);
        // Queue<Integer> queue = new LinkedList<>();
        // while (!in.hasNext("#")) {
        //     queue.offer(in.nextInt());
        // }


        BTNode root = new BTNode();

        // 创建二叉树

        // 方法1:从先序中创建
        // 直接int数组转为Queue:
        // int[] arr = {1, 2, 4, 0, 0, 0, 3, 5, 0, 0, 0}; //【例1】
        // int[] arr = {1, 2, 0, 4, 0, 0, 3, 5, 0, 0, 0}; //【例2】
        // Queue<Integer> queue = Arrays.stream(arr).boxed().
        //         collect(Collectors.toCollection(LinkedList::new));
        // root = createFromPre(root, queue); //从先序中创建

        // 方法2:从层序中创建
        int[] arr = {1, 2, 3, 4, 0, 5, 0}; //【例1】
        // int[] arr = {1, 2, 3, 0, 4, 5, 0}; //【例2】
        root = createFromLevel(arr); //从层序中创建

        System.out.println("三种层序遍历:");
        System.out.println(levelOrderRecursion(new ArrayList<>(), root));
        System.out.println(levelOrderIteration(new ArrayList<>(), root));
        System.out.println(eachLevelOrderIteration(new ArrayList<>(), root));

        System.out.println("三种先序遍历:");
        // System.out.println(preOrderTraversal(root));
        System.out.println(preOrderRecursion(new ArrayList<>(), root));
        System.out.println(preOrderIteration(new ArrayList<>(), root));
        System.out.println(preOrderMorris(new ArrayList<>(), root));

        System.out.println("三种中序遍历:");
        System.out.println(inOrderRecursion(new ArrayList<>(), root));
        System.out.println(inOrderIteration(new ArrayList<>(), root));
        System.out.println(inOrderMorris(new ArrayList<>(), root));

        System.out.println("三种后序遍历:");
        System.out.println(postOrderRecursion(new ArrayList<>(), root));
        System.out.println(postOrderIteration(new ArrayList<>(), root));
        System.out.println(postOrderMorris(new ArrayList<>(), root));

    }

    /**
     * 从先序建立二叉树,0表示停止延伸。停止延伸时,叶子节点后面要有2个0才算停止延伸。
     * 例1:
     *     1
     *   2   3
     * 4    5
     * 先序为,1 2 4 0 0 0 3 5 0 0 0
     *
     * 例2:
     *     1
     *   2   3
     *    4 5
     * 先序为,1 2 0 4 0 0 3 5 0 0 0
     *
     * 中序为,0 2 4 1 5 3 0 ?这个可以搞定吗?感觉搞不定,你上来就空,让人怎么接?
     *
     * 后序为,0 4 2 5 0 3 1 ?这个呢?
     *
     */
    public static BTNode createFromPre(BTNode curr, Queue<Integer> queue) {
        //这个i有问题啊,根本没法当指针用!你需要回传i(return 2个值,要么用list,要么用对象),
        // 或者干脆用queue来控制!!
        int curr_val = queue.poll();
        if (curr_val == 0) {
            return null;
        }

        curr.val = curr_val;
        curr.lc = new BTNode();
        curr.rc = new BTNode();

        curr.lc = createFromPre(curr.lc, queue);
        curr.rc = createFromPre(curr.rc, queue);

        return curr;
    }

    /**
     * 从层序创建二叉树,用的是下标。【不知道有没有递归的方法???】
     *
     *
     * 从层序创建二叉树,0表示为空,以#结束。与上面的停止延伸还有所不同,叶子节点不用输入2个0。
     *
     * 例子:
     *     1
     *   2   3
     * 4    5
     * 层序为,1 2 3 4 0 5 0
     *
     *
     * 问题:
     *  1、传入的root没有用到,而是新建的root,返回的也是新建的root。如果必须要用到传入root的话,0要单独处理!
     *  2、log是以e为底的对数,如果以2为底,得除以log(2)。应该是(Math.log(n + 1) / Math.log(2)),而非 Math.log(n + 1)。
     *  3、求2的幂次方,应该用Math.pow(2, i),不能用2^i。2^0是2,因为^是异或符号,不是多少次方!!!
     *
     *
     * 【不行了,脑子不够用了,撤吧,明天再搞!!!-1:53】
     * 全部搞定了,开干,2021-8-1 22:01:09
     * 终于OK啦!2021-8-2 03:13:01
     *
     */
    public static BTNode createFromLevel(int[] arr) {
        int n = arr.length;
        int h = (int) ((Math.log(n + 1) / Math.log(2)) - 1); //log是以e为底的对数,如果以2为底,得除以log(2)

        List<BTNode> bt = new ArrayList<>();
        for (int i = 0; i <= h; i++) { //层编号i,从0开始,最大为h。
            int num = (int) Math.pow(2, i); // 这一层的个数【按满二叉树】。 不能用2^i,2^0是2。因为^是异或符号,不是多少次方!!!
            int start = num - 1; // 从0开始。
            int end = start + num - 1; // 2*num-2
            //先把数都存进去
            for (int j = start; j <= end; j++) {
                BTNode tmp = new BTNode(arr[j]);
                bt.add(tmp);
            }
        }

        //再连接父子节点
        BTNode root = connectChilds(bt);

        return root;
    }

    /**
     * 把List中的所有节点连接为一棵树。
     * List[0]为root节点。
     * 返回root。
     *
     * 具体实现:
     *  (1)为当前节点i连接左右孩子。i是编号,从0开始。
     *  (2)i的左孩子编号为1+2i,右孩子编号为2+2i。
     *
     //连接父子,两种办法:
     // 1.计算父亲的下标
     //   大前提:编号从0开始!
     //   由2-结论,可以推出,编号j的父亲编号为(j-1)/2。
     //   由2-副结论,可以推出,第j个结点的父亲是第j/2个结点。
     //
     // 2.计算孩子下标
     //   大前提:编号从0开始!
     //   结论:编号j的左孩子编号为1+2j。
     //   副结论:第j个结点的左孩子是第2j个结点。
     //
     //   [推导过程]
     //
     //   当前j,求第一个孩子编号:
     //      (1)第一个孩子编号=1+j+后面弟弟数+前面哥哥的孩子个数 (2)二叉树,前面哥哥的孩子个数=哥哥数*2
     //   当前在这一层中排第几个至关重要:
     //      (1)第k+1个,前面k个哥哥,后面num-k-1个弟弟。(2)k = j-前i层个数 = j-(num-1)
     //   第一个孩子编号 = 1 + j + (num-k-1) + k*2 = 1 + j + { num - [ j-(num-1) ] -1 } + [ j-(num-1) ] * 2
     //                 = 1 + j + { num - [ j-num+1 ] -1 } + 2j-2num+2
     //                 = 1 + j + { num - j + num - 1 -1 } + 2j-2num+2
     //                 = 1 + j + { 2num - j - 2 } + 2j-2num+2
     //                 = 1 + 2j
     //   结论:编号j的左孩子编号为1+2j。【这里的j是编号,是第j+1个结点!】
     //
     //   副结论:第j个结点的左孩子是第2j个结点。
     //      第j+1个结点的左孩子是第(2j+2)个结点。即第j个结点的左孩子是第2j个结点!
     //
     //   我也太棒了吧,我自己推导出来的!!!赞赞赞!!!
     *
     * @param list
     * @return
     */
    private static BTNode connectChilds(List<BTNode> list) {
        for (int i = 0; (2 + 2 * i) < list.size(); i++) {
            BTNode cur = list.get(i);
            cur.lc = list.get(1 + 2 * i);
            cur.rc = list.get(2 + 2 * i);
        }
        return list.get(0);
    }


    /**
     * 层序,递归,按照每一层输出
     *
     * 由于递归方法levelOrderRecursion_Height()只能输出第height层。
     * 所以需要在外层加个循环,来遍历所有的层。
     *
     * height树高,需要调用height()方法求。
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> levelOrderRecursion(List list, BTNode root) {
        int height = height(root);
        for (int i = 1; i <= height; i++) {
            List<Integer> tmp = new LinkedList();
            list.add(levelOrderRecursion_Height(tmp, root, i));
        }
        return list;
    }

    /**
     * 层序,递归【输出第height层】
     *
     * 思路:加个参数,树高。
     *
     * 这个只能打印第“height”层的节点。所以需要在外层加个循环,来遍历所有的层。
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> levelOrderRecursion_Height(List<Integer> list, BTNode root, int height) {
        if (height == 1) {
            if (root != null) {
                // System.out.println(root.val);
                list.add(root.val);
            } else {
                // System.out.println("空");
                list.add(null);
            }
            return list;
        }
        list = levelOrderRecursion_Height(list, root.lc, height - 1);
        list = levelOrderRecursion_Height(list, root.rc, height - 1);

        return list;
    }

    /**
     * 求树高,递归
     *
     * @param root
     * @return
     */
    private static int height(BTNode root) {
        if (root == null) {
            return 0;
        }
        return Math.max(height(root.lc), height(root.rc)) + 1;
    }

    /**
     * 层序=广度优先,迭代
     * 使用队列
     *
     * 【应该没写完吧?】【OK了,之前出错是存入左右孩子时没有判空!现在没问题。2021-8-1 17:26:54】
     *
     * @param list
     * @param root
     * @return
     */
    public static List<Integer> levelOrderIteration(List<Integer> list, BTNode root) {
        BTNode curr = root;
        Queue<BTNode> queue = new LinkedList();
        queue.offer(curr);
        while (!queue.isEmpty()) {
            curr = queue.poll();
            list.add(curr.val);
            // System.out.print(curr.val + " ");

            if (curr.lc != null) {
                queue.offer(curr.lc);
            }
            if (curr.rc != null) {
                queue.offer(curr.rc);
            }
        }
        return list;
    }

    /**
     * 层序,迭代,按照每一层输出
     * 使用两个队列,交替执行【用李喜旺牛腩饭中的萝卜想通的】
     *
     * 具体实现:不按照“交替”,而是按照“临时-赋值”。
     *  1、如果按照交替,两个while代码除了1和2交换,完全冗余。有划线,强迫症受不了。
     *  2、按照临时-赋值,每次都是先把queue1一个个往外出,孩子全都临时存在queue2,最后queue1空之后,把queue2全都放回queue1,queue2清空。
     *
     * 完美! 2021-8-1 17:10:46
     *
     * @param list
     * @param root
     * @return
     */
    public static List<Integer> eachLevelOrderIteration(List list, BTNode root) {
        BTNode curr = root;
        Queue<BTNode> queue1 = new LinkedList();
        Queue<BTNode> queue2 = new LinkedList();
        queue1.offer(curr);

        while (!queue1.isEmpty() || !queue2.isEmpty()) {
            LinkedList<Integer> tmpList1 = new LinkedList<>();
            while (!queue1.isEmpty()) {
                curr = queue1.poll();
                // System.out.print(curr.val + ",");
                tmpList1.add(curr.val);
                if (curr.lc != null) {
                    queue2.offer(curr.lc);
                }
                if (curr.rc != null) {
                    queue2.offer(curr.rc);
                }
            }
            // System.out.println();
            list.add(tmpList1);
            queue1.addAll(queue2);
            queue2.clear();
        }
        return list;
    }

    /**
     * 后序,递归
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> postOrderRecursion(List<Integer> list, BTNode root) {
        if (root == null) {
            return list;
        }
        postOrderRecursion(list, root.lc);
        postOrderRecursion(list, root.rc);
        list.add(root.val);
        return list;
    }

    /**
     * 后序,迭代
     *
     * 与先序迭代的区别:
     * 1、输出时,新的要插到前面。这是为了保证后序,最后输出根。
     * 2、左右子树入栈顺序,是先左后右。因为插到前面顺序正好与先序反着,先序是先右后左。
     *
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> postOrderIteration(List<Integer> list, BTNode root) {
        if (root == null) {
            return list;
        }

        Stack<BTNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            BTNode cur = stack.pop();
            list.add(0, cur.val);
            if (cur.lc != null) {
                stack.push(cur.lc);
            }
            if (cur.rc != null) {
                stack.push(cur.rc);
            }
        }

        return list;
    }

    /**
     * 后序,Morris
     *
     * 先序DLR逆序输出?不行!问题在输出的是RLD,不是LRD!!
     *
     * 他人思路:【太妙了】
     * 1、dump.lc = root:
     *  cur从虚拟节点dump开始,而不是从root开始。。
     *  这是为了把最后一个节点输出,否则会剩下最右节点无法输出,绝妙。
     *  (不加dump最右节点无法输出,加上dump,dump无法输出,相当于往后赶了一步)
     *
     * 2、输出:大顺序小逆序,从cur_lc到pre的逆序
     *  在删除索引后输出从cur_lc到pre整个路径的逆序,其他地方均不输出。
     *  index保证,小序列内部逆序,但整体还是顺序往大序列后添加的!
     *
     *
     * 理解两方面:【不要妄想一口吃个胖子,先1后2,不急着先2】
     * 1、知道他说的是啥:理解他如何实现,能走通数据结构。【主要看图,走数据结构】
     * 2、知道他为什么这么说:理解他设计的针对点,妙在哪里,怎么想出来的?
     *  怎么想出来的?
     *      (1)dump。是发现最后一个节点无法输出,再往下走一步就可以输出了!
     *      (2)逆序输出cur_lc到pre。【这个还不知道怎么想的?】
     *      (3)index。这个是发现应该大顺序,小逆序,如果不用index,就全是逆序,也不行。
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> postOrderMorris(List<Integer> list, BTNode root) {
        BTNode dump = new BTNode();
        dump.lc = root;

        BTNode cur = dump;
        BTNode pre = null;

        while (cur != null) {
            if (cur.lc == null) {
                cur = cur.rc;
            } else {
                pre = cur.lc;
                while (pre.rc != null && pre.rc != cur) {
                    pre = pre.rc;
                }

                if (pre.rc == null) {
                    pre.rc = cur;
                    cur = cur.lc;
                } else {
                    int index = list.size(); //这个index可以保证,每次添加的小序列内部是逆序,但是大序列中还是往整个list后添加的!

                    BTNode cur_lc = cur.lc;

                    while (cur_lc != pre) {
                        list.add(index, cur_lc.val); //这个之前错弄成了cur.val
                        cur_lc = cur_lc.rc;
                    }
                    list.add(index, pre.val); //终止条件之后,再加进去一个pre。

                    pre.rc = null;
                    cur = cur.rc;
                }
            }
        }

        return list;
    }

    /**
     * 中序,递归
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> inOrderRecursion(List<Integer> list, BTNode root) {
        if (root == null) {
            return list;
        }

        inOrderRecursion(list, root.lc);
        list.add(root.val);
        inOrderRecursion(list, root.rc);

        return list;
    }

    /**
     * 中序,迭代
     *
     * 1、左链入栈:先把左子树全部入栈,直到最左边的叶子。
     * 2、栈不空时,弹出一个节点,输出val。
     * 3、无论栈空不空,每次都要对右孩子继续做“左链入栈”。
     * 4、循环退出条件,stack空且当前节点为空。
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> inOrderIteration(List<Integer> list, BTNode root) {
        Stack<BTNode> stack = new Stack();
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.lc;
            }
            if (!stack.isEmpty()) {
                root = stack.pop();
                list.add(root.val);
            }
            //其实这个地方,有点像Morris的方法,只不过Morris用了叶子的指针存,而不是stack。
            // 一旦弹出一个节点,对右孩子继续做“左链入栈”
            root = root.rc;
        }
        return list;
    }

    /**
     * 中序,Morris
     * 其实也是迭代,不用栈的特殊迭代。
     *
     * 把二叉树拉直成链表。【也不是】
     * 把rc当成链表的next指针。
     *
     * 2、我的理解:Morris是用时间换空间。其实还不如用stack呢!【错了】
     *
     * 一直往左走,每次左不空就先标索引(左子树最右节点为pre),往左走。cur=cur.lc。
     * 直到左为空,就把cur输出,
     *      如果cur不是叶子,就是往右子树走。cur=cur.rc。
     *      如果cur是叶子,就是根据索引返回父节点。仍然是cur=cur.rc。
     *
     * 返回父节点后,再查一次pre,发现pre.rc=cur,则输出当前父亲(cur),并且把索引删掉。
     * 然后就遍历右子树啦。cur=cur.rc。
     *
     * 2个地方输出:输出后都是往右走,因为输出的是中。
     *      左空,输出cur,往右走/返回父亲,都是cur=cur.rc。
     *      左不空,且pre.rc==cur,输出cur,往右走cur=cur.rc。
     *
     * 往左走:
     *      只要左不空就标索引pre.rc=cur,标完索引往左走cur=cur.lc。
     *
     *
     * 3、空间和时间复杂度:
     * 空间复杂度为O(1):不用栈而是借助叶子的右指针不费空间,只用到了一个pre用O(1)。
     * 时间复杂度是O(n):
     * 每次查询所谓“前驱节点”其实就是找到左子树的最右节点,每个节点都要查两遍左子树,一遍是加索引,一遍是删索引。
     * 看似涉及树高度,是O(nlgn),实际上是每条边最多走两遍,是O(2n)也就是O(n)。
     *
     *
     * @param list
     * @param root
     * @return
     */
    private static List<Integer> inOrderMorris(List<Integer> list, BTNode root) {
        BTNode cur = root;
        BTNode pre = null;
        while (cur != null) {
            if (cur.lc == null) {
                list.add(cur.val);
                cur = cur.rc;
            } else {
                pre = cur.lc;
                while (pre.rc != null && pre.rc != cur) {//找到最右节点,即为pre。
                    pre = pre.rc;
                }
                if (pre.rc == null) {
                    pre.rc = cur;
                    cur = cur.lc;
                } else { // pre.rc == cur
                    pre.rc = null;
                    list.add(cur.val); //与先序唯一的不同之处,是在删索引的时候输出!!!
                    cur = cur.rc;
                }
            }
        }
        return list;
    }

    /**
     * 这个纯粹是为了迎合Offer07的参数列表要求
     * @param root
     * @return
     */
    public static List<Integer> preOrderTraversal(BTNode root) {
        List<Integer> list = new ArrayList();
        list = preOrderRecursion(list, root);

        return list;
    }

    /**
     * 先序,递归
     *
     * @param list
     * @param root
     * @return
     */
    public static List<Integer> preOrderRecursion(List<Integer> list, BTNode root) {
        if (root == null) {
            return list;
        }

        list.add(root.val);

        list = preOrderRecursion(list, root.lc);
        list = preOrderRecursion(list, root.rc);
        return list;
    }

    /**
     * 先序,迭代
     *
     * 竟然用栈来实现,而且是先右后左!我惊呆了!!!
     * 我一直以为是队列。。。。
     *
     * @param list
     * @param root
     * @return
     */
    public static List<Integer> preOrderIteration(List<Integer> list, BTNode root) {
        if (root == null) {
            return list;
        }
        Stack<BTNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            BTNode curr = stack.pop();
            list.add(curr.val);
            if (curr.rc != null) {
                stack.push(curr.rc);
            }
            if (curr.lc != null) {
                stack.push(curr.lc);
            }
        }

        return list;
    }

    /**
     * Morris的先序方法,也是迭代。
     *
     * 与中序唯一的不同之处,是在加索引前输出!!!
     *
     * @param list
     * @param root
     * @return
     */
    public static List<Integer> preOrderMorris(List<Integer> list, BTNode root) {
        BTNode cur = root;
        BTNode pre = null;
        while (cur != null) {
            if (cur.lc == null) {
                list.add(cur.val);
                cur = cur.rc;
            } else {
                pre = cur.lc;
                while (pre.rc != null && pre.rc != cur) {
                    pre = pre.rc;
                }

                if (pre.rc == null) {
                    list.add(cur.val); //与中序唯一的不同之处,是在加索引前输出!!!

                    pre.rc = cur;
                    cur = cur.lc;
                } else { //pre.rc == cur
                    pre.rc = null;
                    cur = cur.rc;
                }

            }
        }
        return list;
    }
}

class BTNode {
    int val;
    BTNode lc;
    BTNode rc;

    public BTNode() {
    }

    public BTNode(int val) {
        this.val = val;
        this.lc = null;
        this.rc = null;
    }
}

/**
 * 不限子节点个数的一般树,用左孩子和右兄弟
 */
class GeneralTreeNode {
    int val;
    GeneralTreeNode left_child;
    GeneralTreeNode right_sibling;

}

 

 

2、输出结果:

三种层序遍历:
[[1], [2, 3], [4, 0, 5, 0]]
[1, 2, 3, 4, 0, 5, 0]
[[1], [2, 3], [4, 0, 5, 0]]
三种先序遍历:
[1, 2, 4, 0, 3, 5, 0]
[1, 2, 4, 0, 3, 5, 0]
[1, 2, 4, 0, 3, 5, 0]
三种中序遍历:
[4, 2, 0, 1, 5, 3, 0]
[4, 2, 0, 1, 5, 3, 0]
[4, 2, 0, 1, 5, 3, 0]
三种后序遍历:
[4, 0, 2, 5, 0, 3, 1]
[4, 0, 2, 5, 0, 3, 1]
[4, 0, 2, 5, 0, 3, 1]

 

 

问题:

1、从层序创建二叉树,目前是用下标。有没有递归/迭代的方法?

2、层序,有没有Morris方法?

3、可以从中序创建二叉树吗?后序呢?

4、从先序+中序 创建二叉树?

 

 

 

posted on 2021-08-02 03:51  西伯尔  阅读(789)  评论(0编辑  收藏  举报