1. 程式人生 > 其它 >根據遍歷結果構造二叉樹

根據遍歷結果構造二叉樹

技術標籤:資料結構與演算法

根據遍歷結果構造二叉樹

根據遍歷結果構造二叉樹

只能通過前序和中序,或者中序和後續唯一確認一棵二叉樹,而前序和後序無法做到。

1)前序和中序結果倒推二叉樹

思路:
先根據前序結果,找到根節點
找到中序結果中根節點的位置,確認左右子樹的個數

切出左子樹的前序和中序結果,再按照此方法推進,
直到推匯出葉子節點的位置,反倒推出整棵樹。

0 1 2 3 4

1 2 3 4 5

3 4 2 1 5

根節點在中序中的位置是3 (左子樹的大小)

leftSize = 3

左子樹的前序和中序
切分的區間是左閉右開

2 3 4 [1,leftSize+1)

3 4 2 [0,leftSize)

右子樹的前序和中序

5 [leftSize+1,end)

5 [leftSize+1,end)

image-20201016161906642
 public static TreeNode buildTree(int[] preOrder, int[] inOrder) {

        // 遞迴出口
        if (preOrder.length == 0) return null;

        // 在前序結果中  找到根節點
        int rootValue = preOrder[0];
        TreeNode root = new TreeNode(rootValue);

        // 查詢根節點在中序結果中的位置
        int leftSize = find(inOrder, rootValue);

        // 切分出左子樹的前序和中序結果
        // 使用 Arrays.copyOfRange方法  三個引數  原始陣列 起始位置 終止位置
        //  [起始位置,終止位置)
        //
        // 2 3 4  [1,leftSize+1)
        //
        // 3 4 2  [0,leftSize)
        int[] leftPreOrder = Arrays.copyOfRange(preOrder, 1, leftSize + 1);
        int[] leftInOrder = Arrays.copyOfRange(inOrder, 0, leftSize);
        root.left = buildTree(leftPreOrder, leftInOrder);

        // 切分出右子樹的前序和中序結果
        //
        // 5  [leftSize+1,end)
        // 5  [leftSize+1,end)
        int[] rightPreOrder = Arrays.copyOfRange(preOrder, leftSize + 1, preOrder.length);
        int[] rightInOrder = Arrays.copyOfRange(inOrder, leftSize + 1, inOrder.length);
        root.right = buildTree(rightPreOrder, rightInOrder);

        return root;
    }


    public static int find(int[] array, int value) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == value) {
                return i;
            }
        }
        return -1;
    }

2)中序和後序結果倒推二叉樹

0 1 2 3 4

3 4 2 1 5

4 3 2 5 1

根節點在中序中的位置是3 (左子樹的大小)
leftSize = 3

左子樹的中序和後序
切分的區間是左閉右開

3 4 5 [0,leftSize)
4 3 2 [0,leftSize)

右子樹的中序和後序

5 [leftSize+1,end)
5 [leftSize,end-1)

public static TreeNode buildTree1(int[] inOrder, int[] postOrder) {

        // 遞迴出口
        if (inOrder.length == 0 || postOrder.length == 0) return null;

        // 在前序結果中  找到根節點
        int rootValue = postOrder[postOrder.length - 1];
        TreeNode root = new TreeNode(rootValue);

        // 查詢根節點在中序結果中的位置
        int leftSize = find(inOrder, rootValue);

        // 切分出左子樹的中序和後序結果
        // 使用 Arrays.copyOfRange方法  三個引數  原始陣列 起始位置 終止位置
        //  [起始位置,終止位置)
        //
        // 3 4 5   [0,leftSize)
        // 4 3 2   [0,leftSize)
        int[] leftInOrder = Arrays.copyOfRange(inOrder, 0, leftSize);
        int[] leftPostOrder = Arrays.copyOfRange(postOrder, 0, leftSize);
        root.left = buildTree1(leftInOrder, leftPostOrder);

        // 切分出右子樹的中序和後序結果
        //
        // 5  [leftSize+1,end)
        // 5  [leftSize,end-1)
        int[] rightInOrder = Arrays.copyOfRange(inOrder, leftSize + 1, inOrder.length);
        int[] rightPostOrder = Arrays.copyOfRange(postOrder, leftSize, postOrder.length - 1);
        root.right = buildTree1(rightInOrder, rightPostOrder);

        return root;
    }