平衡二叉树(AVL树)

来来来,今天我们来看看平衡二叉树(又叫AVL树)


平衡二叉树是二叉排序树的一个进化体,也是第一个引入平衡概念的二叉树。因为它的“平衡”,所以是一个很优秀的数据存储结构。此数据结构插入、查找和删除的时间复杂度均为O(logN),但是插入和删除需要额外的旋转算法需要的时间,有时旋转过多也会影响效率。

平衡二叉树实现的大部分过程和二叉查找树是一样的(学平衡二叉树之前一定要会二叉排序树),区别就在于插入和删除之后要写一个旋转算法去维持平衡,维持平衡需要借助一个节点高度的属性。

平衡二叉树且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

由此概念,我们可以定义它的结构了。


//定义平衡二叉树的结构
typedef struct BNODE
{
int data;         //数据
int bf;             //判断子树间的高度差
struct BNODE *lchild, *rchild;//左子树和右子树
}BNODE,*BTree;



因为插入数据可能会导致二叉树的的高度增高,进而不平衡了,所以我们就要通过旋转来维持平衡


//对二叉树的右旋操作
void RRotate(BTree *p)
{
BTree L;
L = (*p)->lchild;//L指向P的左子树根结点
(*p)->lchild = L->rchild;//L的右子树挂接为p的左子树
L->rchild = (*p);
*p = L;//p指向新的根节点
}


//对二叉树的左旋操作
void LRotate(BTree *p)
{
BTree L;
L = (*p)->rchild;
(*p)->rchild = L->lchild;
L->lchild = (*p);
(*p) = L;
}


//左平衡旋转

#define  LH 1
#define  EH 0
#define  RH -1


void LeftBalance(BTree *T)
{
BTree L, Lr;
L = (*T)->lchild;//L指向T的左子树根节点

switch (L->bf)//检查T的左子树的平衡度,并作相应平衡处理
{
case LH://新节点插在T的左孩子的左子树上,要作右旋处理
(*T)->bf = L->bf = EH;
RRotate(T);
break;


case  RH://新节点插在T的左孩子的右子树上,要作双旋处理
Lr = L->rchild;//Lr指向T的左孩子的右子树根
switch (Lr->bf)
{
case  LH:
(*T)->bf = RH;
L->bf = EH;
break;

case  EH:
(*T)->bf = L->bf = EH;
break;

case  RH:
(*T)->bf = EH;
L->bf = LH;
break;
}
Lr->bf = EH;
LRotate(&(*T)->lchild);//对T的左子树作左旋平衡处理
RRotate(T);//对T作右旋平衡处理
}


}



//插入操作

bool Insert(BTree *T, int e, bool *t)//t反应树T长高与否,ture为长高,false不长高
{
if (!*T)//插入新节点,树长高
{
*T = (BTree)malloc(sizeof(BNODE));
(*T)->data = e;
(*T)->lchild = (*T)->rchild = NULL;
(*T)->bf = EH;
*t = true;
}
else
{
if (e == (*T)->data)//树中已经存在相同的数据就不再插入
{
*t = false;
return false;
}
if ((*T)->data > e)//在T的左子树中继续寻找
{
if (!Insert(&(*T)->lchild, e, t))//未插入
return false;
if (*t)//已插入到T的左子树中且左子树已经长高了
switch ((*T)->bf)//检查T的平衡度
{
case LH://左子树比右子树高,需要左平衡处理
LeftBalance(T);
*t = true;
break;
case EH://原本左右子树等高,现在因为左子树增高而树也增高了
(*T)->bf = LH;
*t = true;
break;
case RH://原本右子树比左子树高,现在左右子树等高
(*T)->bf = EH;
*t = false;
break;
}
}
else
{
if (!Insert(&(*T)->rchild, e, t))//未插入
return false;
if (*t)//已插入到T的右子树中且右子树已经长高了
switch ((*T)->bf)//检查T的平衡度
{
case LH://左子树比右子树高,现在左右子树等高
(*T)->bf = EH;
*t = false;
break;
case EH://原本左右子树等高,现在因为右子树增高而树也增高了
(*T)->bf = LH;
*t = true;
break;
case RH://原本右子树比左子树高,需要又平衡处理
RightBalance(T);
*t = false;
break;
}
}


}




return true;


}





发布了29 篇原创文章 · 获赞 9 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章