平衡二叉搜索树
AVL树的实现
- 二叉搜索树在插入和删除时,节点可能发生失衡;
- 如果在插入和删除时通过旋转,始终让二叉搜索树保持平衡,称之为平衡二叉搜索树;
- AVL树是自平衡二叉搜索树的实现之一
LL
- 失衡节点(图中5红色)的`bf>1`,即左边更高
- 失衡节点的左孩子(图中3 黄色)的`bf>=0`,即左孩子这边也是左边更高或等高
LR
- 失衡节点(图中6)的`bf>1`,即左边更高
- 失衡节点的左孩子(图中2 黄色)的`bf<0`,即左孩子这边是右边更高
RL
-失衡节点(图中2)的`bf<-1`,即右边更高
-失衡节点的右孩子(图中6黄色)的`bf>0`,即右孩子这边是左边更高
RR
-失衡节点(图中2红色)的`bf<-1`,即右边更高
-失衡节点的右孩子(图中6黄色)的`bf<=0`,即右孩子这边是右边更高或者等高
public class AVLTree{
static class AVLNode{
int key;
Object value;
AVLNode left;
AVLNode right;
int height = 1;
public AVLNode (int key, Object value) {
this.key = key;
this.value = value;
}
public AVLNode (int key) {
this.key = key;
}
public AVLNode (int key, Object value, AVLNode left, AVLNode right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
// 求节点高度
public int height(AVLNode node) {
return node == 0 ? 0 : node.height;
}
// 更新节点高度(新增、删除、旋转)
public void updateHeight(AVLNode node) {
node.height = Math.max(height(node.left), height(node.right)) + 1;
}
// 平衡因子(balance factor) = 左子树高度-右子树高度
// bf = 0, -1, 1, 表示左右平衡
// bf > 1, 表示左子树高
// bf < -1, 表示右子树高
public int bf(TreeNode node) {
return height(node.left) - height(node.right);
}
// 输入要旋转的节点,返回新节点----右旋
private AVLNode rightRotate(AVLNode red) {
AVLNode yellow = red.left;
AVLNode green = yellow.right;
yellow.right = red;
red.left = green;
updateHeight(red);
updateHeight(yellow);
return yellow;
}
// 输入要旋转的节点,返回新节点----左旋
private AVLNode leftRotate(AVLNode red) {
AVLNode yellow = red.right;
AVLNode green = yellow.left;
yellow.left = red;
red.righ = green;
updateHeight(red);
updateHeight(yellow);
return yellow;
}
// 先左旋,后右旋----先左旋左子树,后右旋根节点
private AVLNode leftRightRotate(AVLNode node) {
node.left = leftRotate(node.left);
return rightRotate(node);
}
// 先右旋右子树,后左旋根节点
private AVLNode rightLeftRotate(AVLNode node) {
node.right = rightRotate(node.right);
return leftRotate(node);
}
// 检查是否平衡
private AVLNode balance(AVLNode node) {
if (node == null) {
return node;
}
int bf = bf(node);
if (bf > 1 && bf(node.left) >= 0) { //LL
rightRotate(node);
} else if (bf > 1 && bf(node.left) < 0) { // LR
leftRightRotate(node);
} else if (bf < -1 && bf(node.right) > 0) { // RL
rightLeftRotate(node);
} else if (bf < -1 && bf(node.right) <= 0) { // RR
leftRotate(node);
}
}
AVLNode root;
public void put(int key, Object value) {
return doPut(root, key, value);
}
private ALVNode doPut(AVLNode node, int key, Object value) {
// 1.找到空位,创建新节点
if (node == null) {
return new AVLNode(key, value);
}
// 2.树中存在节点,做更新操作
if (node.key == key) {
node.value = value;
return node;
}
// 3.查找操作
if (key < node.key) {
node.left = doPut(node.left, key, value);
}
if (key > node.key) {
node.right = doPut(node.right, key, value);
}
// 更新高度,检查是否平衡
updateHeight(node);
return balance(node);
}
public void remove(int key) {
root = doRemove(root, key);
}
public AVLNode doRemove(AVLNode node, int key) {
// 1.节点为空
if (node == null) {
return null;
}
// 2.寻找节点
if (key < node.key) {
node.left = doRemove(node.left, key);
} else if (key > node.key) {
node.right = doRemove(node.right, key);
} else {
// 3.找到节点,判断删除节点是否有孩子
if (node.left == null && node.right == null) {
return null;
} else if(node.left == null) {
node = node.right;
} else if (node.right == null) {
node = node.left;
} else { // 左右子树均在
// 在待删除节点的右子树zhon寻找待删除节点的后继节点
AVLNode s = node.right;
while (s.left != null) {
s = s.left;
}
// 找到后继节点
s.right = doRemove(node.right, s.key);
s.left = node.left;
node = s;
}
}
updateHeight(node);
return balance(node);
}
}
删除操作
Remove(node.right, s.key);
s.left = node.left;
node = s;
}
}
updateHeight(node);
return balance(node);
}
}
删除操作
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c65de9476563476ebd30192166eb8b07.png#pic_center)