樹的遍歷,重建二叉樹

詳見jiyangg.github.io(二叉樹集錦)html

二叉樹節點:node

class BinaryTreeNode {
    int val;
    BinaryTreeNode left;
    BinaryTreeNode right;

    public BinaryTreeNode(int val) {
        this.val = val;
    }
}

訪問節點操做

void visit(BinaryTreeNode node) {
    System.out.print(node.val + " ");
}

二叉樹節點數目

  • 若是是空樹:返回0
  • 若是不是空樹:節點數 = (左子樹節點數)+(右子數節點數) + 1
int TreeNodeCount(BinaryTreeNode root) {
    if (root == null) {
        return 0;
    }
    return TreeNodeCount(root.left) + TreeNodeCount(root.right) + 1;
}

求二叉樹深度

  • 若是是空樹:返回0
  • 若是不是空樹:深度 = Max(左子樹深度,右子樹深度) + 1
int TreeDepth(BinaryTreeNode root) {
    if (root == null) {
        return 0;
    }
    int leftDepth = TreeDepth(root.left);
    int rightDepth = TreeDepth(root.right);
    return leftDepth > rightDepth ? (leftDepth + 1) : (rightDepth + 1);
}

前序遍歷

  • 若是是空樹:return
  • 若是不是空樹:根->左->右
void preOrderTraverse(BinaryTreeNode root) {
    if (root == null) {
        return;
    }
    visit(root);                    //訪問根節點
    preOrderTraverse(root.left);    //前序遍歷左子樹
    preOrderTraverse(root.right);   //前序遍歷右子樹
}

中序遍歷

  • 若是是空樹:return
  • 若是不是空樹:左->根-右
void inOrderTraverse(BinaryTreeNode root) {
    if (root == null) {
        return;
    }
    inOrderTraverse(root.left);     //中序遍歷左子樹
    visit(root);                    //訪問根節點
    inOrderTraverse(root.right);    //中序遍歷右子樹
}

後序遍歷

  • 若是是空樹:return
  • 若是不是空樹:左->右->根
void postOrderTraverse(BinaryTreeNode root) {
    if (root == null) {
        return;
    }
    postOrderTraverse(root.left);    //後序遍歷左子樹
    postOrderTraverse(root.right);   //後序遍歷右子樹
    visit(root);                    //訪問根節點
}

層序遍歷(從上到下,從左到右)

  • 使用隊列實現:
    • 隊列初始化:將根節點入隊
    • 當隊列不爲空:彈出一個節點,訪問,若左節點或右節點不爲空,將其入隊
void levelTraverse(BinaryTreeNode root){
    if (root == null) {
        return;
    }
    Queue<BinaryTreeNode> queue = new ArrayDeque<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        BinaryTreeNode node = queue.poll();
        visit(node);
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
    }

重建二叉樹

根據前序遍歷和中序遍歷的結果重建二叉樹git

經過前序遍歷的第一個元素爲樹的根找到根節點,而後在中序遍歷中找到根節點的位置就能肯定樹的左右子樹的節點數。github

BinaryTreeNode reConstructBinaryTree(int[] pre, int[] in) {
    if (pre == null || in == null || pre.length <= 0 || in.length <= 0) {
        return null;
    }
    //儲存根節點
    BinaryTreeNode root = new BinaryTreeNode(pre[0]);
    int rootPositionInOrder = -1;
    //查找根節點在中序遍歷的位置
    for (int i = 0; i < in.length; i++) {
        if (root.val == in[i]) {
            rootPositionInOrder = i;
            break;
        }
    }
    if (rootPositionInOrder == -1) {
        return null;
    }
    //肯定左子樹節點數
    int numOfLeft = rootPositionInOrder;
    //存儲左子樹前序遍歷結果
    int[] leftPre = new int[numOfLeft];
    for (int i = 0; i < numOfLeft; i++) {
        leftPre[i] = pre[i + 1];
    }
    //儲存左子樹中序遍歷結果
    int[] leftIn = new int[numOfLeft];
    for (int i = 0; i < numOfLeft; i++) {
        leftIn[i] = in[i];
    }
    //重建左子樹
    root.left = reConstructBinaryTree(leftPre, leftIn);

    //肯定右子樹節點數
    int numOfRight = in.length - numOfLeft - 1;
    //儲存右子樹前序遍歷結果
    int[] rightPre = new int[numOfRight];
    for (int i = 0; i < numOfRight; i++) {
        rightPre[i] = pre[i + numOfLeft + 1];
    }
    //儲存右子樹中序遍歷結果
    int[] rightIn = new int[numOfRight];
    for (int i = 0; i < numOfRight; i++) {
        rightIn[i] = in[i + numOfLeft + 1];
    }
    //重建右子樹
    root.right = reConstructBinaryTree(rightPre, rightIn);

    return root;
}
相關文章
相關標籤/搜索