📅  最后修改于: 2023-12-03 15:09:38.278000             🧑  作者: Mango
在二叉搜索树(BST)中,插入一组有序数据可能导致树变得不平衡,使得某些节点的深度比其他节点更深。为了保持树的平衡,我们可以使用平衡搜索树。(Balanced BST)
平衡搜索树有许多种类型,其中最常见的是AVL树和红黑树。不同的平衡树有不同的平衡策略和旋转操作,但是它们都确保节点平衡,从而保证树的高度为 O(log n)。
下面介绍一种方法将一个正常的二叉搜索树转换为平衡搜索树。这里使用AVL树作为示例。
为了将BST转换为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 旋转操作,以确保树的平衡性。