我们先来分析AVL的高度
node.heigh= Math.max(getHeigh(node.left),getHeigh(node.right))+1;`
首先,我们向二叉树插入数据18和45,插入18的时候,根据上述代码,我们从20的左右子节点找到一个高度最高的,也就是30
所在的位置高度1,然后再+1得到20节点所在的高度。我们再插入45的时候,取30左右子节点的最大高度,30的左子节点为null,所以右子节点高度为1,也就是30的高度为2.此时回溯到20节点,20节点的左右子节点最大节点为30高度为2,再加1就是3了。再回溯到根节点15.。。
其实从上面不难看出,我们只要求左右节点的最大高度,然后再加上本身节点的具有的高度1,就的得到了节点的高度,然后依次回溯
我们再来分析平衡因子
首先,这是一棵平衡二叉树,平衡因子就是在二叉树中,左子树的高度和右子树的高度差不可能超过1.
如果我们任由平衡因子增大,也就是左右子树的增大,那么就会出现链表化的情况,导致查找成本增加,O(logN)的时间复杂度会退化成O(n)时间复杂度如下图所示:
int balance = Math.abs(getBalance(node));
if (balance!=1){
System.out.println("不平衡");
}
return node;
public int getBalance(Node node){
if(null=node)
return 0;
return getHeigh(node.left)-getHeigh(node.right);
}
旋转后就变成这样
右旋转代码
public Node rightRoate(Node node){
Node x=node.left;
Node T=x.right;
x.right=node;
node.left=T;
//这里的+1 只是重新计算,并不是意味着直接+1
node.heigh=Math.max(getHeigh(node.left),getHeigh(node.right))+1;
x.heigh=Math.max(getHeigh(x.left),getHeigh(x.right))+1;
//这里很巧妙的用到了 return node 作为上个栈帧对象引用赋值
return x;
}
左旋转
public Node leftRoate(Node node){
Node x= node.right;
Node T=x.left;
x.left=node;
node.right=T;
node.heigh=Math.max(getHeigh(node.left),getHeigh(node.right))+1;
x.heigh=Math.max(getHeigh(x.left),getHeigh(x.right))+1;
return x;
}
返回值很有意义,直接更新在树形结构上的结点。
AVL树代码
static class BST{
Node root;
//root结点
public BST(Node root){
this.root=root;
}
//插入操作
private Node insert(Node node,int data){
if (null==node){
return new Node(data);
}
if (node.data>data){
node.left=insert(node.left,data);
}else if (node.data<data){
node.right=insert(node.right,data);
}
node.heigh= Math.max(getHeigh(node.left),getHeigh(node.right))+1;
int balance = getBalance(node);
//LL
if (balance<-1&&getBalance(node.right)<=0){
return leftRoate(node);
}
//RR
if (balance>1&&getBalance(node.left)>=0){
return rightRoate(node);
}
//LR
if (balance>1&&getBalance(node.left)<0){
node.left=leftRoate(node.left);
return rightRoate(node);
}
//RL
if (balance<-1&&getBalance(node.right)>0){
node.right=rightRoate(node.right);
return leftRoate(node);
}
return node;
}
public int getBalance(Node node){
if(node == null)
return 0;
return getHeigh(node.left)-getHeigh(node.right);
}
public Node rightRoate(Node node){
Node x=node.left;
Node T=x.right;
x.right=node;
node.left=T;
//这里的+1 只是重新计算,并不是意味着直接+1
node.heigh=Math.max(getHeigh(node.left),getHeigh(node.right))+1;
x.heigh=Math.max(getHeigh(x.left),getHeigh(x.right))+1;
//这里很巧妙的用到了 return node 作为上个栈帧对象引用赋值
return x;
}
public Node leftRoate(Node node){
Node x= node.right;
Node T=x.left;
x.left=node;
node.right=T;
node.heigh=Math.max(getHeigh(node.left),getHeigh(node.right))+1;
x.heigh=Math.max(getHeigh(x.left),getHeigh(x.right))+1;
return x;
}
public int getHeigh(Node node){
if (node==null){
return 0;
}
return node.heigh;
}
//插入操作
public void insert(int data){
insert(root,data);
}
}
RR、LL、RL和LR
RR 不平衡节点 后连续两个都是右子节点 只要左旋转
LL 不平衡节点 后连续两个都是左子节点 只要右旋转
RL 不平衡节点 先右后左 节点 先右旋转再左旋转
LR 不平衡节点 先左后右 节点 先左旋转再右旋转