性质:
-
1.AVL树是一棵二叉查找树
-
2.对于其任意结点,其 左子树 与 右子树 的高度之差(平衡因子)的绝对值不超过1
定义初始化:
struct node
{
int data;
int height;//当前子树高度
node *lchild;
node *rchild;
};
node* newnode(int v)
{
node* Node=new node;
Node->data=v;
Node->lchild=Node->rchild=NULL;
Node->height=1;//结点高度初始化为1
return Node;
}
要计算平衡因子总的知道它的左右子树的高度,再计算
int getheight(node* root)
{
if(root==NULL)
return 0;
return root->height;
}
int getbalancefactor(node* root)
{
return getheight(root->lchild)-getheight(root->rchild);
}
完了,左旋右旋之后要更新你的结点高度
void updateheight(node* root)
{
root->height=max(getheight(root->lchild),getheight(root->rchild))+1;
}
插入操作:
进行左右旋,使其平衡因子<=1,看图写代码( * ^ ▽ ^ * )
左旋
void L(node* &root)
{
node* temp=root->rchild;
root->rchild=temp->lchild;
temp->lchild=root;
updateheight(root);
updateheight(temp);
root=temp;
}
右旋
void R(node* &root)
{
node* temp=root->lchild;
root->lchild=temp->rchild;
temp->rchild=root;
updateheight(root);
updateheight(temp);
root=temp;
}
在理解左右旋的基础上可以进行插入操作了,因为是在原先的一棵平衡二叉树上进行的操作,所以插入操作一定在底层的两棵子树上,对于插入操作,插入后会出现四种形态,LL,LR,RR,RL。
1.LL型(以A为根结点右旋)
2.LR型(先以C为根结点左旋,再以A为根结点右旋)
3.RR型(以A为根结点左旋)
4.RL型(先以C为根结点右旋,再以A为根结点左旋)
插入操作的代码块类似于二叉排序树的插入方式,每次插入完毕后 需要更新当前结点高度以及 调整成AVL形态
void Insert(node* &root,int v)
{
if(root==NULL)
{
root=newnode(v);
return;
}
if(v<root->data)
{
Insert(root->lchild,v);
updateheight(root);
if(getbalancefactor(root)==2)
{
if(getbalancefactor(root->lchild)==1)//LL
{
R(root);
}
else if(getbalancefactor(root->lchild)==-1)//LR
{
L(root->lchild);
R(root);
}
}
}
else
{
Insert(root->rchild,v);
updateheight(root);
if(getbalancefactor(root)==-2)
{
if(getbalancefactor(root->rchild)==-1)//RR
{
L(root);
}
else if(getbalancefactor(root->rchild)==1)//RL
{
R(root->rchild);
L(root);
}
}
}
}