📜  将正常的BST转换为平衡的BST(1)

📅  最后修改于: 2023-12-03 15:09:38.278000             🧑  作者: Mango

将正常的BST转换为平衡的BST

在二叉搜索树(BST)中,插入一组有序数据可能导致树变得不平衡,使得某些节点的深度比其他节点更深。为了保持树的平衡,我们可以使用平衡搜索树。(Balanced BST)

平衡搜索树有许多种类型,其中最常见的是AVL树和红黑树。不同的平衡树有不同的平衡策略和旋转操作,但是它们都确保节点平衡,从而保证树的高度为 O(log n)。

下面介绍一种方法将一个正常的二叉搜索树转换为平衡搜索树。这里使用AVL树作为示例。

思路

为了将BST转换为AVL树,我们需要执行以下步骤:

  1. 将BST转换为排序数组。
  2. 使用排序数组构建AVL树。

由于二叉搜索树中的节点按值从小到大排序,我们可以通过中序遍历将它们全部放在一个数组中。然后,从数组的中间位置开始,我们可以递归地将数组的左半部分构建为AVL树的左子树,将数组的右半部分构建为右子树。AVL的平衡性质在树构建中自动得到了保证。

代码实现

以下是Java代码实现,我们声明一个TreeNode类型的参数,为一棵BST,返回值是一棵AVL树。

private TreeNode balanceBST(TreeNode root) {
    List<Integer> nums = new ArrayList<>();
    inorder(root, nums);
    return buildAVL(nums, 0, nums.size() - 1);
}

private void inorder(TreeNode node, List<Integer> nums) {
    if (node != null) {
        inorder(node.left, nums);
        nums.add(node.val);
        inorder(node.right, nums);
    }
}

private TreeNode buildAVL(List<Integer> nums, int start, int end) {
    if (start > end) {
        return null;
    }
    int mid = (end - start) / 2 + start;
    TreeNode root = new TreeNode(nums.get(mid));
    root.left = buildAVL(nums, start, mid - 1);
    root.right = buildAVL(nums, mid + 1, end);
    root.height = Math.max(getHeight(root.left), getHeight(root.right)) + 1;
    int balance = getBalance(root);
    if (balance > 1 && getBalance(root.left) >= 0) {
        return rotateRight(root);
    }
    if (balance > 1 && getBalance(root.left) < 0) {
        root.left = rotateLeft(root.left);
        return rotateRight(root);
    }
    if (balance < -1 && getBalance(root.right) <= 0) {
        return rotateLeft(root);
    }
    if (balance < -1 && getBalance(root.right) > 0) {
        root.right = rotateRight(root.right);
        return rotateLeft(root);
    }
    return root;
}

private int getHeight(TreeNode node) {
    return node == null ? 0 : node.height;
}

private int getBalance(TreeNode node) {
    return node == null ? 0 : getHeight(node.left) - getHeight(node.right);
}

private TreeNode rotateLeft(TreeNode node) {
    TreeNode right = node.right;
    TreeNode left = right.left;
    right.left = node;
    node.right = left;
    node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
    right.height = Math.max(getHeight(right.left), getHeight(right.right)) + 1;
    return right;
}

private TreeNode rotateRight(TreeNode node) {
    TreeNode left = node.left;
    TreeNode right = left.right;
    left.right = node;
    node.left = right;
    node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
    left.height = Math.max(getHeight(left.left), getHeight(left.right)) + 1;
    return left;
}

该代码中,我们使用了一个辅助的 height 属性来记录每个节点的高度值,并实现了 AVL 旋转操作,以确保树的平衡性。