一、AVL树定义
它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。
二叉排序树定义:
一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
二、AVL树相关概念
1)平衡因子:将二叉树上节点的左子树高度减去右子树高度的值称为该节点的平衡因子BF(Balance Factor)。
2)最小不平衡子树:距离插入节点最近的,且平衡因子的绝对值大于1的节点为根的子树.。
3)四种调整类型:在一个平衡二叉树上插入新数据的过程中,可能会导致平衡二叉树不平衡,分为LL、LR、RR、RL四种类型。
三、AVL树的自平衡调整
平衡二叉树结构定义:
class AVLNode {
int val;
int height;
AVLNode left = null;
AVLNode right = null;
public AVLNode(int val, int height) {
this.val = val;
this.height = height;
}
}
1、LL型
由于新插入的节点 1 ,使得节点 3 的平衡因子由 1 变为了 2,使得其不再平衡。调整方法如下:
- 先将节点 2 的右子树放在一边;
- 将节点 2 提升为根节点;
- 让节点 3 做节点 2 的右子树;
- 最后节点 2 的右子树做为节点 3 的左子树。
代码实现:
private AVLNode ll_rotate(AVLNode root) {
AVLNode newRoot = root.left;
root.left = newRoot.right;
newRoot.right = root;
root.height = Math.max(getHeight(root.left), getHeight(root.right)) + 1;
newRoot.height = Math.max(getHeight(newRoot.left), getHeight(newRoot.right)) + 1;
return newRoot;
}
2、RR型
此种情况和LL型对应,根节点 3 的平衡因子由-1变为了-2从而失衡,调整方法与LL型相反。
代码实现:
private AVLNode rr_rotate(AVLNode root) {
AVLNode newRoot = root.right;
root.right = newRoot.left;
newRoot.left = root;
root.height = Math.max(getHeight(root.left), getHeight(root.right)) + 1;
newRoot.height = Math.max(getHeight(newRoot.left), getHeight(newRoot.right)) + 1;
return newRoot;
}
调整完之后要记得重新计算新节点的高度!!!
3、LR型
由于节点 1 的右子树插入了新结点使节点 3 的平衡因子从1变为了2,显然是新结点作为根节点,然后节点1和3作为两个孩子。
也可以分成两部分理解,先将LR型调整为LL型,也就是先对根结点的左孩子进行调整,对其进行RR型的调整,然后对根节点进行LL型调整。
代码实现:
private AVLNode lr_rotate(AVLNode root) {
root.left = rr_rotate(root.left);
return ll_rotate(root);
}
4、RL型
由于在节点3的左子树上插入了新结点,根节点的平衡因子由-1变为了-2,调整方法和LR型对应,先对节点3进行LL型调整,就变成了RR型,然后对根节点进行RR型调整。
代码实现:
private AVLNode rl_rotate(AVLNode root) {
root.right = ll_rotate(root.right);
return rr_rotate(root);
}
AVL树的实现代码
public class Main {
public static void main(String[] args) {
Main s = new Main();
AVLNode root = null;
root = s.insert(root, 5);
root = s.insert(root, 3);
root = s.insert(root, 4);
root = s.insert(root, 1);
root = s.insert(root, 7);
root = s.insert(root, 9);
root = s.insert(root, 0);
//s.preOrder(root);
root = s.delete(root, 1);
s.preOrder(root);
}
private void preOrder(AVLNode root) {
if(root == null) return ;
preOrder(root.left);
System.out.println(root.val);
preOrder(root.right);
}
private AVLNode ll_rotate(AVLNode root) {
AVLNode newRoot = root.left;
root.left = newRoot.right;
newRoot.right = root;
root.height = Math.max(getHeight(root.left), getHeight(root.right)) + 1;
newRoot.height = Math.max(getHeight(newRoot.left), getHeight(newRoot.right)) + 1;
return newRoot;
}
private AVLNode rr_rotate(AVLNode root) {
AVLNode newRoot = root.right;
root.right = newRoot.left;
newRoot.left = root;
root.height = Math.max(getHeight(root.left), getHeight(root.right)) + 1;
newRoot.height = Math.max(getHeight(newRoot.left), getHeight(newRoot.right)) + 1;
return newRoot;
}
private AVLNode lr_rotate(AVLNode root) {
root.left = rr_rotate(root.left);
return ll_rotate(root);
}
private AVLNode rl_rotate(AVLNode root) {
root.right = ll_rotate(root.right);
return rr_rotate(root);
}
private int getHeight(AVLNode root) {
if(root == null) return 0;
else return root.height;
}
private int getBalance(AVLNode root) {
if(root == null) return 0;
else return getHeight(root.left) - getHeight(root.right);
}
private AVLNode insert(AVLNode node, int val) {
if(node == null) {
return new AVLNode(val, 1);
}
if(val > node.val) {
node.right = insert(node.right, val);
} else if (val < node.val) {
node.left = insert(node.left, val);
} else {
return node;
}
node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));
int balance = getBalance(node);
if(balance > 1 && val < node.left.val) {
return ll_rotate(node);
}
if(balance > 1 && val > node.left.val) {
return lr_rotate(node);
}
if(balance < -1 && val > node.right.val) {
return rr_rotate(node);
}
if(balance < -1 && val < node.right.val) {
return rl_rotate(node);
}
return node;
}
private AVLNode getMinValueNode(AVLNode root) {
while(root.left != null) root = root.left;
return root;
}
private AVLNode delete(AVLNode root, int val) {
if(root == null) return null;
if(root.val > val) {
root.left = delete(root.left, val);
} else if (root.val < val) {
root.right = delete(root.right, val);
} else {
if(root.left == null || root.right == null) {
AVLNode temp = root.left != null ? root.left : root.right;
root = temp;
} else {
AVLNode temp = getMinValueNode(root.right);
root.val = temp.val;
root.right = delete(root.right, temp.val);
}
if(root == null) return null;
root.height = Math.max(getHeight(root.left), getHeight(root.right)) + 1;
int balance = getBalance(root);
if(balance > 1 && val < root.left.val) {
return ll_rotate(root);
}
if(balance > 1 && val > root.left.val) {
return lr_rotate(root);
}
if(balance < -1 && val > root.right.val) {
return rr_rotate(root);
}
if(balance < -1 && val < root.right.val) {
return rl_rotate(root);
}
}
return root;
}
}
class AVLNode {
int val;
int height;
AVLNode left = null;
AVLNode right = null;
public AVLNode(int val, int height) {
this.val = val;
this.height = height;
}
}