一、AVL树的四种旋转操作
(1)右旋
代码:
/**
* 右旋
*
* @param root
* @return
*/
private AvlNode rigthRotate(AvlNode root) {
AvlNode newroot = root.left;
root.left = newroot.right;
newroot.left = root;
root.height = Math.max(height(root.left), height(root.right)) + 1;
newroot.height = Math.max(height(newroot.left), height(newroot.right)) + 1;
return newroot;
}
(2)左旋
代码:
/**
* AVL树的左旋转操作,从root开始,进行左旋,完成后,把新的根节点返回
*
* @param root
* @return
*/
private AvlNode leftRotate(AvlNode root) {
AvlNode newroot = root.right;
root.right = newroot.left;
newroot.left = root;
root.height = Math.max(height(root.left), height(root.right)) + 1;
newroot.height = Math.max(height(newroot.left), height(newroot.right)) + 1;
return newroot;
}
(3) 左右旋
代码:
/**
* 左右旋转
*
* @param root
* @return
*/
private AvlNode leftBalance(AvlNode root) {
root.left = leftRotate(root.left);
return rigthRotate(root);
}
(4)右左旋
代码:
/**
* 右左旋转
*/
private AvlNode rightBalance(AvlNode root) {
root.right = rigthRotate(root.right);
return leftRotate(root);
}
二、AVL树的插入和删除
(1)插入
/**
* 插入操作
*
* @param val
* @return
*/
public void insert(int val) {
root = insert(root, val);
}
private AvlNode insert(AvlNode root, int val) {
if (root == null) {
return new AvlNode(val, null, null, 1);
}
if (val > root.data) {
root.right = insert(root.right, val);
if (height(root.right) - height(root.left) > 1) {
if (val > root.right.data) { //插入到右孩子的右子树 进行LL旋转
root = leftRotate(root);
} else {
root = rightBalance(root); //插入到右子树的左子树 进行RL旋转
}
}
} else if (val < root.data) {
root.left = insert(root.left, val);
if (height(root.left) - height(root.right) > 1) {
if (val < root.left.data) { //插入到左孩子的左子树 进行RR
root = rigthRotate(root);
} else {
root = leftBalance(root); //插入到左孩子的右子树 进行RL旋转
}
}
} else {
System.out.println("不能插入相同的结点");
}
//由于插入了新的结点 ,需要更新树的高度;
root.height = Math.max(height(root.left), height(root.right)) + 1;
return root;
}
(2)删除操作
/**
* 删除结点
*/
public void remove(int val) {
remove(root, val);
}
private AvlNode remove(AvlNode root, int val) {
if (root == null) {
return null;
}
if (val > root.data) {
root.right = remove(root.right, val);
if (height(root.left) - height(root.right) > 1) {
//判断要删除的结点在左孩子的那个子树上 此时结点已删除 只能从左子树高度来判断
if (height(root.left.left) >= height(root.left.right)) { //左孩子的右子树高
root = rigthRotate(root);
} else { //左孩子的左子树高
root = leftBalance(root);
}
}
} else if (val < root.data) {
root.left = remove(root.left, val);
if (height(root.right) - height(root.left) > 1) {
//判断要删除的结点在右孩子的那个子树上
if (height(root.right.left) > height(root.right.right)) { //右孩子的左子树高
root = rightBalance(root);
} else { //右孩子的右子树高
root = leftRotate(root);
}
}
} else {
if (root.left != null && root.right != null) {
//判断root的左子树高,用前驱(左孩子的右子树)代替
if (height(root.left) > height(root.right)) {
AvlNode tmp = root.left;
while (tmp.right != null) {
tmp = tmp.right;
}
root.data = tmp.data;
root.left = remove(root.left, tmp.data);
} else { //右子树高 用后继(右孩子的左子树)代替
AvlNode tmp = root.right;
while (tmp.left != null) {
tmp = tmp.left;
}
root.data = tmp.data;
root.right = remove(root.right, tmp.data);
}
} else {
if (root.right != null) {
return root.right;
}
if (root.left != null) {
return root.left;
}
return null;
}
}
root.height = Math.max(height(root.left), height(root.right)) + 1;
return root;
}