二叉樹創建(從先序、層序、先序+后序)


 

 

創建二叉樹的方式,目前掌握的三種:

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、從先序+中序 創建二叉樹?

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM