二叉排序树的查询性能和二叉树的结构有关,如果二叉排序树退化为单链表,那么查询时间就是O(n),而平衡二叉树使得左右子树高度差不超过1,因此查询效率高,为O(log2n)。
性质:左子树和右子树都是平衡二叉树,且左右子树高度差的绝对值不超过1。
平衡因子:右子树减去左子树的高度差。
当平衡因子大于1时,则失去平衡,需要调整失去该平衡的最小子树。在插入的过程中会碰到四种插入情况,需要不同的调整方式。
分别是:
- LL平衡旋转:在当前节点的左孩子的左子树上插入新结点,导致该节点的平衡因子变为-2,需要LL平衡旋转。
- RR平衡旋转:在当前节点的右孩子的右子树上插入新节点,导致该节点的平衡因子变为2,需要RR平衡旋转。
- LR平衡旋转:在当前节点的左孩子的右子树上插入新节点,导致该节点的平衡因子变为-2,需要LR平衡旋转。
- RL平衡旋转:在当前节点的右孩子的左子树上插入新节点,导致该节点的平衡因子变为2,需要RL平衡旋转。
在插入的过程中,每次插入一个数需要根据平衡因子判断是否失去了平衡,然后调整。需要平衡旋转的最小子树的层数在旋转前后都未曾改变,因此子树之上的节点不需要调整平衡因子。
下面的程序使用avl算法实现了平衡二叉树的插入和删除。
public class App
{
public static void main(String[] arg) {
int[]array= {11,39,23,68,85,8,3,46,27,50};
BBTree bTree=new BBTree(array);
bTree.preOrder();
System.out.println("");
bTree.delete(39);
bTree.delete(27);
bTree.preOrder();
}
//平衡二叉树,实现算法AVL
static class BBTree{
class Node{
int data;
Node leftChild,rightChild;
int balance;//平衡因子
}
Node root;
public BBTree(int[] array) {
// TODO Auto-generated constructor stub
for(int a:array) {
insert(a);
// preOrder();
// System.out.println("");
}
}
void preOrder() {
preOrder(root);
}
void preOrder(Node p) {
if(p==null) {
return;
}
System.out.print(p.data+" ");
preOrder(p.leftChild);
preOrder(p.rightChild);
}
void insert(int k) {
if(root==null) {
root=new Node();
root.data=k;
return ;
}
Node a=root;
Node preA=null;//a的前一个取值
Node cur=root;
while(true) {
if(k<cur.data) {
if(cur.leftChild!=null) {
if(Math.abs(cur.balance)==1) {
preA=a;
a=cur;
}
cur=cur.leftChild;
}else {
if(Math.abs(cur.balance)==1) {
preA=a;
a=cur;
}
cur.leftChild=new Node();
cur.leftChild.data=k;
//从a修改balance
updateBalance(k, a);
//若不平衡则调整
if(Math.abs(a.balance)==2) {
//adjust tree
if(a==root) {//根节点特殊处理
root=rotate(a);
}else if(preA.leftChild==a) {
preA.leftChild=rotate(a);
}else {
preA.rightChild=rotate(a);
}
}
return;
}
}else if(k>cur.data) {
if(cur.rightChild!=null) {
if(Math.abs(cur.balance)==1) {
preA=a;
a=cur;
}
cur=cur.rightChild;
}else {
if(Math.abs(cur.balance)==1) {
preA=a;
a=cur;
}
cur.rightChild=new Node();
cur.rightChild.data=k;
updateBalance(k, a);
if(Math.abs(a.balance)==2) {
if(a==root) {
root=rotate(a);
}else if(preA.leftChild==a) {
preA.leftChild=rotate(a);
}else {
preA.rightChild=rotate(a);
}
}
return;
}
}
}
}
void updateBalance(int k,Node p) {
//更新平衡因子,如果p为null,默认使用root
if(p==null) {
p=root;
}
while(p.data!=k) {
if(k<p.data) {
p.balance--;
p=p.leftChild;
}else if(k>p.data){
p.balance++;
p=p.rightChild;
}
}
}
/***
* 自动根据平衡因子分辨LL、LR、RR、RL四种情况,然后调整
* @param a 该节点平衡因子必须大于1,即不平衡
* @return 返回新根节点
*/
Node rotate(Node a) {
if(Math.abs(a.balance)<=1) {
return null;
}
if(a.leftChild!=null && a.leftChild.balance==-1) {
//LL
Node b=a.leftChild;
Node temp=b.rightChild;
b.rightChild=a;
a.leftChild=temp;
//修改平衡因子
a.balance=getBalance(a);
b.balance=getBalance(b);
return b;
}else if(a.leftChild!=null && a.leftChild.balance==1) {
//LR
Node b=a.leftChild;
Node c=b.rightChild;
Node temp1=c.leftChild,temp2=c.rightChild;
c.leftChild=b;
c.rightChild=a;
b.rightChild=temp1;
a.leftChild=temp2;
a.balance=getBalance(a);
b.balance=getBalance(b);
c.balance=getBalance(c);
return c;
}else if(a.rightChild!=null&&a.rightChild.balance==-1) {
//RL
Node b=a.rightChild;
Node c=b.leftChild;
Node temp1=c.leftChild,temp2=c.rightChild;
c.leftChild=a;
c.rightChild=b;
a.rightChild=temp1;
b.leftChild=temp2;
a.balance=getBalance(a);
b.balance=getBalance(b);
c.balance=getBalance(c);
return c;
}else if(a.rightChild!=null&&a.rightChild.balance==1) {
//RR
Node b=a.rightChild;
Node temp=b.leftChild;
b.leftChild=a;
a.rightChild=temp;
a.balance=getBalance(a);
b.balance=getBalance(b);
return b;
}
return null;
}
/***
* 得到关于该节点的高度
* @param p
* @return
*/
int getHeight(Node p) {
if(p==null) {
return 0;
}
int height1=getHeight(p.leftChild);
int height2=getHeight(p.rightChild);
return Math.max(height1, height2)+1;
}
/***
* 得到该节点的平衡因子
* @param p
* @return
*/
int getBalance(Node p) {
int left=getHeight(p.leftChild);
int right=getHeight(p.rightChild);
return right-left;
}
void delete(int k) {
root=delete(k, root);
}
boolean shorter=true;
Node delete(int k,Node p) {
if(p==null) {//没有该元素
shorter=false;
return null;
}
if(k<p.data) {
p.leftChild=delete(k, p.leftChild);
//判断shorter
if(shorter) {
if(p.balance==1) {
Node q=p.rightChild;
if(q.balance==1) {
shorter=true;
p=rotate(p);
}else if(q.balance==0) {//不属于四种平衡旋转之一。。。
shorter=false;
Node temp=q.leftChild;
q.leftChild=p;
p.rightChild=temp;
q.balance=getBalance(q);
p.balance=getBalance(p);
p=q;//要返回p,而p是根节点。
}else if(q.balance==-1) {
shorter=true;
p=rotate(p);
}
}else if(p.balance==0) {
p.balance=getBalance(p);
shorter=false;
}else if(p.balance==-1) {
p.balance=getBalance(p);
shorter=true;
}
}
return p;
}else if(k>p.data){
p.rightChild=delete(k, p.rightChild);
//判断shorter
if(shorter) {
if(p.balance==1) {
shorter=true;
p.balance=getBalance(p);
}else if(p.balance==0) {
shorter=false;
p.balance=getBalance(p);
}else if(p.balance==-1) {
Node q=p.leftChild;
if(q.balance==0) {
Node temp=q.rightChild;
q.rightChild=p;
p.leftChild=temp;
shorter=false;
p.balance=getBalance(p);
q.balance=getBalance(q);
p=q;
}else if (q.balance==-1) {
shorter=true;
p=rotate(p);
}else if(q.balance==1) {
shorter=true;
p=rotate(p);
}
}
}
return p;
}else {
shorter=true;
if(p.leftChild!=null&&p.rightChild!=null) {
Node temp=min(p.rightChild);
temp.rightChild=deleteMin(p.rightChild);
temp.leftChild=p.leftChild;
return temp;
}else if(p.leftChild==null) {
return p.rightChild;
}else {
return p.leftChild;
}
}
}
Node min(Node p) {
while(p.leftChild!=null) {
p=p.leftChild;
}
return p;
}
Node deleteMin(Node p) {
if(p.leftChild==null) {
return p.rightChild;
}
p.leftChild=deleteMin(p.leftChild);
return p;
}
}
}