参考:
https://baijiahao.baidu.com/s?id=1651427207567199156&wfr=spider&for=pc
https://blog.csdn.net/bjweimengshu/article/details/106774187
https://blog.csdn.net/QuedYin/article/details/103619681
public class AVLNode {
public int data;
public int depth;
public int balance;
public AVLNode parent;
public AVLNode left;
public AVLNode right;
public AVLNode(int data){
this.data=data;
this.balance=0;
left=null;
right=null;
}
//插入
public void insert(AVLNode root,int data){
//递归向左子树插入
if(data<root.data){
if(root.left!=null){
insert(root.left,data);
}
else{
root.left=new AVLNode(data);
root.left.parent=root;
}
}
//递归向右子树插入
else{
if(root.right!=null){
insert(root.right,data);
}
else{
root.right=new AVLNode(data);
root.right.parent=root;
}
}
//插入之后计算平衡因子
root.balance=calcBalance(root);
//左子树高,右旋
if(root.balance>=2){
//左孙低,右孙高,先左旋
if(root.left.balance==-1){
left_rotate(root.left);
}
right_rotate(root);
}
//右子树高,左旋
if(root.balance<=-2){
//左孙高,先右旋
if(root.right.balance==1){
right_rotate(root.right);
}
left_rotate(root);
}
//调整后,重新计算平衡因子和长度
root.balance=calcBalance(root);
root.depth=calcDepth(root);
}
//右旋
public void right_rotate(AVLNode p){
AVLNode pParent=p.parent;
AVLNode pLeftSon=p.left;
AVLNode pRightGrandSon=pLeftSon.right;//这个节点的左孩子的右节点
//左子变父 使这个节点的左孩子替代它在父亲那里的位置
pLeftSon.parent=pParent;
//使这个节点的左孩子替代它在父亲那里的位置
if(pParent!=null){
if(p==pParent.left){
pParent.left=pLeftSon;
}
else if(p==pParent.right){
pParent.right=pLeftSon;
}
}
pLeftSon.right=p;//使这个节点成为原来的左孩子的右节点
p.parent=pLeftSon;//使这个节点成为原来的左孩子的右节点
//右孙变左孙
//因为这个节点占了原来的左孩子的右节点pRightGrandSon的位置,所以pRightGrandSon需要 新位置
//而pRightGrandSon原来在这个节点的左子树中, 必定小于这个节点,所以让她成为这个节点的左孩子
p.left=pRightGrandSon;//左孩子设置为pRightGrandSon
if(pRightGrandSon!=null){//pRightGrandSon的父亲设为p
pRightGrandSon.parent=p;
}
//重新计算p和pLeftSon的depth和balance
p.depth=calcDepth(p);
p.balance=calcBalance(p);
pLeftSon.depth=calcDepth(pLeftSon);
pLeftSon.balance=calcBalance(pLeftSon);
}
//左旋 (右子树高的情况)
public void left_rotate(AVLNode p){
AVLNode pParent=p.parent;
AVLNode pRightSon=p.right;//这个节点的右孩子
AVLNode pLeftGrandSon=pRightSon.left;//这个节点的右孩子的左节点,因为这个节点将要替代他,所以要处理他
pRightSon.parent=pParent;//这个节点的右孩子替代了这个节点在父亲那的位置
//这个节点的右孩子替代了这个节点在父亲那的位置
if(pParent!=null){
if(p==pParent.right){
pParent.right=pRightSon;
}else if(p==pParent.left){
pParent.left=pRightSon;
}
}
pRightSon.left=p;//这个节点替代了它的右孩子的左节点
p.parent=pRightSon;
p.right=pLeftGrandSon;//它的右孩子的左节点无处可去,因为原来在他右子树,所以必定比这个节点大,让他成为这个节点的右孩子
if(pLeftGrandSon!=null){
pLeftGrandSon.parent=p;
}
p.depth=calcDepth(p);
p.balance=calcBalance(p);
pRightSon.depth=calcDepth(pRightSon);
pRightSon.balance=calcBalance(pRightSon);
}
//计算平衡
public int calcBalance(AVLNode p){
int d1=0;
int d2=0;
if(p.left!=null){
d1=p.left.depth;
}
if(p.right!=null){
d2=p.right.depth;
}
return d1-d2;
}
//计算深度
public int calcDepth(AVLNode p){
int depth=0;
if(p.left!=null){
depth=p.left.depth;
}
if(p.right!=null){
if(p.right.depth>depth){
depth=p.right.depth;
}
}
return depth;
}
}