操作有左旋rr,右旋ll,左右旋lr,右左旋rl,插入新节点insert(四种旋转都涉及,而且左右旋和右左旋只有插入时才会用到),平衡操作balance(确保一个点平衡,要么不旋转要么左旋要么右旋,只在删除时使用),删除erase(删除一个节点并平衡整棵树),另外两个dfs_show_me_the_tree和inorder在main中作为检验的方法。
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
struct node
{
node*lch,*rch;
int key;
node(int x):key(x){lch=rch=nullptr;}
};
using ptr=node*;
//取子树p的深度,检验平衡性时使用
int deep(ptr p)
{
if(!p)return 0;
return max(deep(p->lch),deep(p->rch))+1;
}
//ll指插入左子树的左子树失衡,要右旋,这里“ll”跟“右”在字面上是相反的
ptr ll(ptr p)
{
ptr l=p->lch;
p->lch=l->rch,l->rch=p;
return l;
}
//rr指插入右子树的右子树失衡,要左旋,这里“rr”跟“左”在字面上是相反的
ptr rr(ptr p)
{
ptr r=p->rch;
p->rch=r->lch,r->lch=p;
return r;
}
//rl指插入右子树的左子树失衡,右旋右子树再左旋自己,这里“r-l”跟“右-左”恰巧一样
ptr rl(ptr p)
{
p->rch=ll(p->rch);
return rr(p);
}
//lr指插入左子树的右子树失衡,左旋左子树再右旋自己,这里“l-r”跟“左-右”恰巧一样
ptr lr(ptr p)
{
p->lch=rr(p->lch);
return ll(p);
}
//在erase中使用的小工具
ptr balance(ptr p)
{
if(deep(p->lch)-deep(p->rch)==2)
return ll(p);
if(deep(p->rch)-deep(p->lch)==2)
return rr(p);
return p;
}
ptr insert(ptr p,int x)
{
if(!p)return new node(x);
//插入,如果失衡返回平衡后的p,这里不能使用balance因为balance不需要lr,rl,而这里需要
if(x<p->key)
{
p->lch=insert(p->lch,x);
if((deep(p->lch)-deep(p->rch))==2)
return x<p->lch->key?ll(p):lr(p);
}else
{
p->rch=insert(p->rch,x);
if((deep(p->rch)-deep(p->lch))==2)
return x<p->rch->key?rl(p):rr(p);
}
//如果没有失衡也返回p
return p;
}
ptr erase(ptr p,int x)
{
if(!p)return p;
//如果在p的子树上删除,事后自然要检查p是否失衡
if(x<p->key)p->lch=erase(p->lch,x);
else if(x>p->key)p->rch=erase(p->rch,x);
//x在p这个节点上分为三种情况讨论
//p无左子树直接返回右子树,这个右子树一定没有失衡
else if(!p->lch)
{
ptr r=p->rch;
delete p;return r;
}
//p的左子树无右子树,如下设置后,返回p的左子树,
//只有l可能失衡,l平衡一次
else if(!p->lch->rch)
{
ptr l=p->lch;
l->rch=p->rch;
delete p;return balance(l);
}
//找到如下代码所示的lr,失去lr的l和重新设置的lr都可能失衡,l右旋一次,lr平衡一次
else
{
ptr l=p->lch,lr;
for(l=p->lch;l->rch->rch;l=l->rch);
lr=l->rch,l->rch=lr->lch;
//平衡l没想到好的方法,只好从上往下仔细考量
p->lch=balance(p->lch);
for(l=p->lch;l->rch!=lr->lch;l=l->rch)l->rch=balance(l->rch);
//再配置好lr并平衡
lr->lch=p->lch,lr->rch=p->rch;
delete p;return balance(lr);
}
return balance(p);//该节点及其祖先节点们也不会失衡
}
void dfs_show_me_the_tree(ptr p)
{
if(!p)return;
if(p->lch)
cout<<p->key<<" lch is"<<p->lch->key<<endl;
if(p->rch)
cout<<p->key<<" rch is"<<p->rch->key<<endl;
dfs_show_me_the_tree(p->lch);
dfs_show_me_the_tree(p->rch);
}
void inorder(ptr p)
{
if(!p)return;
inorder(p->lch);
cout<<p->key<<' ';
inorder(p->rch);
}
int main()
{
vector<int>x{3,5,2,7,5,0,1,512,44,-4,2};
ptr avl=nullptr;
cout<<"the inserting process\n";
for(int i=0;i<x.size();++i){avl=insert(avl,x[i]);inorder(avl);cout<<endl;}
cout<<"\nshow the kids of each node\n";
dfs_show_me_the_tree(avl);
cout<<"\nthe deleting process\n";
for(int i=0;i<x.size();++i){avl=erase(avl,x[i]);inorder(avl);cout<<endl;}
}