以此篇告别我琢磨AVL树模板题的2天时间(菜洗了),因为一开始写的树存在值可能相同的节点,导致我被删除节点整麻了,维护节点值不相同就好起来了TUT。
板题链接 洛谷P3369【普通平衡树】
感觉其他博客的AVL树的定义,选择,插入,删除都大差不差,我就直接上码了
首先是节点的定义
struct node{
int date;
int h;
int lsize,size; //lsize表示左子树有多少节点,size表示左子树节点数+右子树节点数+1,即以自身节点当根节点的树的大小
int cnt; //cnt表示值为date的节点有cnt个,因此该AVL树中节点的值互不相同
node* left;
node* right;
node(){ //初始化
left=NULL;
right=NULL;
h=1;
lsize=0;
size=1;
cnt=1;
}
};
接着是一些基本操作
node* creatnode(int x) //创建节点
{
node* t=new node();
t->date=x;
return t;
}
int geth(node* t) //得到该节点的高度
{
if( t==NULL )
return 0;
return t->h;
}
int getsize(node* t) //得到该节点的大小(节点数)
{
if( t==NULL )
return 0;
int tsize=t->cnt;
if( t->left!=NULL ) tsize+=t->left->size;
if( t->right!=NULL ) tsize+=t->right->size;
return tsize;
}
void updateh(node* &t) //更新函数
{
t->lsize=getsize(t->left);
t->size=getsize(t);
t->h=max(geth(t->left),geth(t->right))+1;
}
int getavl(node* t) //返回该节点的平衡因子
{
return geth(t->left)-geth(t->right);
}
接着就是维持平衡的左旋和右旋了
void L(node* &t) //左旋
{
node* temp=t->right;
t->right=temp->left;
temp->left=t;
updateh(t);
updateh(temp);
t=temp;
}
void R(node* &t) //右旋
{
node* temp=t->left;
t->left=temp->right;
temp->right=t;
updateh(t);
updateh(temp);
t=temp;
}
接下来就是操作了。
1.插入
void insert(node* &t,int x)
{
if( t==NULL ) //找到合适位置但当前节点为空,插入
{
t=creatnode(x);
return ;
}
if( x==t->date ) //树中存在值为x的节点,该节点cnt++
{
t->cnt++;
updateh(t);
}
else if( x<t->date ) //x<当前节点值,去左节点查找
{
insert(t->left,x);
updateh(t); //插入完后记得更新节点参数
if( getavl(t)==2 ) //保持平衡操作
{
if( getavl(t->left)==1 )
{
R(t); //LL
}
else
{
L(t->left); //LR
R(t);
}
}
}
else //x>当前节点值,去右节点查找
{
insert(t->right,x);
updateh(t); //插入完后记得更新节点参数
if( getavl(t)==-2 ) //保持平衡操作
{
if( getavl(t->right)==-1