目录
AVL的概念:
* 二叉搜索树在插入和删除时,节点可能失衡 * 插入和删除操作时,需要调整树结构,使树再次平衡这就是自平衡的二叉搜索树 * avl是自平衡的二叉搜索树的一种
节点高度:
private int height(AVLNode node){
return node==null?0:node.height;
}
新增节点高度:
private void updateHeight(AVLNode node){
node.height=Integer.max(height(node.left),height((node.right)))+1;
}
平衡因子:
private int bf(AVLNode node){
return height(node.left)-height(node.right);
}
左旋:
private AVLNode leftRotate(AVLNode node){
AVLNode newRoot=node.right;
AVLNode temp=newRoot.left;
newRoot.left=node;
node.right=temp;
updateHeight(node);
updateHeight(newRoot);
return newRoot;
}
右旋:
private AVLNode rightRotate(AVLNode node){
AVLNode newRoot=node.left;
AVLNode temp=newRoot.right;
newRoot.right=node;//上位
node.left=temp;//换爹
updateHeight(node);//这个高度需要变
updateHeight(newRoot);//这两行的位置不能换,先更新低的高度,再更新高的高度
return newRoot;
}
LR旋:
private AVLNode leftRightRotate(AVLNode node){
node.left=leftRotate(node.left);
return rightRotate(node);
}
RL旋:
private AVLNode rightLeftRotate(AVLNode node){
node.right=rightRotate(node.right);
return leftRotate(node);
}
检查是否失衡:
private AVLNode isBalance(AVLNode node){
if(node==null){
return null;
}
if(bf(node)>1&&bf(node.left)>=0){//LL =0:是左子树平衡,根节点失衡
return rightRotate(node);
}else if(bf(node)>1&&bf(node.left)<0){//LR
return leftRightRotate(node);
}else if(bf(node)<-1&&bf(node.right)>0){//RL
return rightLeftRotate(node);
} else if(bf(node)<-1&&bf(node.right)<=0){//RR =0:是右子树平衡,根节点失衡 发生在删除时
return leftRotate(node);
}
return node;
}
新增节点:
public void put(int key,Object value){
root=doPut(root,key,value);
}
private AVLNode doPut(AVLNode root, int key, Object value) {//root :上一个节点
//1.找到空位,新增节点
if(root==null){
return new AVLNode(key,value);
}
//2.key已存在,更新value
if(key==root.key){
root.value=value;
return root;
}
//3.继续
if(key<root.key){
root.left=doPut(root.left,key,value);
}else{
root.right=doPut(root.right,key,value);
}
//4.更新高度
updateHeight(root);
//5.检查是否失衡
return isBalance(root);
}
删除节点:
public void remove(int key){
root=doRemove(root,key);
}
private AVLNode doRemove(AVLNode root, int key) {
//1.node==null,没找到
if(root==null){
return null;
}
//2没找到
if(key<root.key){
root.left=doRemove(root.left,key);//更新删除后剩余的
}else if(key>root.key){
root.right=doRemove(root.right,key);
}else{
//3.找到,删除节点 1)没有左右孩子 2)只有左孩子 3)只有右孩子 4)左右孩子都有
if(root.left==null&&root.right==null){
return null;
}else if(root.left==null){
root=root.right; //为了继续下面的操作
}else if(root.right==null){
root=root.left;
}else{
AVLNode s=root.right;
while(s.left!=null){//找后继节点
s=s.left;
}
//检查后继节点
s.right=doRemove(root.right,s.key);
s.left=root.left;
root=s;
}
}
//4.更新高度
updateHeight(root);
//5.检查是否失衡
return isBalance(root);
}
完整代码:
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;
}
}
//求节点的高度
private int height(AVLNode node){
return node==null?0:node.height;
}
//更新增删旋转的高度
private void updateHeight(AVLNode node){
node.height=Integer.max(height(node.left),height((node.right)))+1;
}
//平衡因子
/*
* 平衡的:0 1 -1
* 不平衡: <-1 >1
* */
private int bf(AVLNode node){
return height(node.left)-height(node.right);
}
//右旋 节点是要旋转的节点 返回值是新的根节点
private AVLNode rightRotate(AVLNode node){
AVLNode newRoot=node.left;
AVLNode temp=newRoot.right;
newRoot.right=node;//上位
node.left=temp;//换爹
updateHeight(node);//这个高度需要变
updateHeight(newRoot);//这两行的位置不能换,先更新低的高度,再更新高的高度
return newRoot;
}
//左旋
private AVLNode leftRotate(AVLNode node){
AVLNode newRoot=node.right;
AVLNode temp=newRoot.left;
newRoot.left=node;
node.right=temp;
updateHeight(node);
updateHeight(newRoot);
return newRoot;
}
//LR旋 先左旋右子树,再右旋根节点
private AVLNode leftRightRotate(AVLNode node){
node.left=leftRotate(node.left);
return rightRotate(node);
}
//RL旋 先右旋左子树,再左旋根节点
private AVLNode rightLeftRotate(AVLNode node){
node.right=rightRotate(node.right);
return leftRotate(node);
}
//检查是否失衡
private AVLNode isBalance(AVLNode node){
if(node==null){
return null;
}
if(bf(node)>1&&bf(node.left)>=0){//LL =0:是左子树平衡,根节点失衡
return rightRotate(node);
}else if(bf(node)>1&&bf(node.left)<0){//LR
return leftRightRotate(node);
}else if(bf(node)<-1&&bf(node.right)>0){//RL
return rightLeftRotate(node);
} else if(bf(node)<-1&&bf(node.right)<=0){//RR =0:是右子树平衡,根节点失衡 发生在删除时
return leftRotate(node);
}
return node;
}
AVLNode root;
//put 新增节点
public void put(int key,Object value){
root=doPut(root,key,value);
}
private AVLNode doPut(AVLNode root, int key, Object value) {//root :上一个节点
//1.找到空位,新增节点
if(root==null){
return new AVLNode(key,value);
}
//2.key已存在,更新value
if(key==root.key){
root.value=value;
return root;
}
//3.继续
if(key<root.key){
root.left=doPut(root.left,key,value);
}else{
root.right=doPut(root.right,key,value);
}
//4.更新高度
updateHeight(root);
//5.检查是否失衡
return isBalance(root);
}
//删除 remove
public void remove(int key){
root=doRemove(root,key);
}
private AVLNode doRemove(AVLNode root, int key) {
//1.node==null,没找到
if(root==null){
return null;
}
//2没找到
if(key<root.key){
root.left=doRemove(root.left,key);//更新删除后剩余的
}else if(key>root.key){
root.right=doRemove(root.right,key);
}else{
//3.找到,删除节点 1)没有左右孩子 2)只有左孩子 3)只有右孩子 4)左右孩子都有
if(root.left==null&&root.right==null){
return null;
}else if(root.left==null){
root=root.right; //为了继续下面的操作
}else if(root.right==null){
root=root.left;
}else{
AVLNode s=root.right;
while(s.left!=null){//找后继节点
s=s.left;
}
//检查后继节点
s.right=doRemove(root.right,s.key);
s.left=root.left;
root=s;
}
}
//4.更新高度
updateHeight(root);
//5.检查是否失衡
return isBalance(root);
}
}