《数据结构》AVL
AVL的定义
- 属于二叉查找树,左儿子的值<当前的值<右儿子的值。
- 在任意一个节点,左右子树高度差不超过2。
性质
- 左子树中任意一节点的值<当前节点的值<右子树中任意一节点的值
- 高度为h的AVL树,节点最多有2h-1个。
思想
- 通过旋转操作,实现左右子树平衡。
旋转操作(单旋转)
- 左旋
node* levo(node *now)/*左旋,rr,r>l*/
{
node *tem=now->r;
now->r=tem->l;
tem->l=now;
now->h=Max(height(now->l),height(now->r))+1;
tem->h=Max(height(tem->l),height(tem->r))+1;
return tem;
}
/*
k2
/ \
k1 z
/ \
x y
x
形象一下,假如树是柔软的,现在我们提住k1,并把y接到k2的左下。
k1
/ \
x k2
x / \
y z
现在不就平衡了?
*/
- 右旋
node* dext(node *now)/*右旋,ll,l>r*/
{
node *tem=now->l;
now->l=tem->r;
tem->r=now;
now->h=Max(height(now->l),height(now->r))+1;
tem->h=Max(height(tem->l),height(tem->r))+1;
return tem;
}
/*同上*/
但是,我们会发现下面这种情况无法靠单旋转解决
k2
/ \
k1 z
/ \
y x
x
使用单旋转旋后变成
k1
/ \
y k2
/ \
x z
x
依然没有解决问题,为什么呢?
原来在图1中,单旋转并没有改变x的深度,而是改变了y和k1的深度,这时我们就该用到双旋转了!
- 左右旋
node* lext(node *now)/*左右旋,lr,l>r*/
{
now->l=levo(now->l);
return dext(now);
}
/*
是不是很简单?
其实也不难理解-》就是先通过对左子树进行一次左旋,使高度高的x旋转至左儿子,再通过右旋转使其平衡
*/
- 右左旋
node* devo(node *now)/*右左旋,rl,r>l*/
{
now->r=dext(now->r);
return levo(now);
}
解决了这些,剩下的便是小菜一碟了
代码如下:# define Type template<typename T>
Type const T Max(T a,T b){return a>b?a:b;}
Type struct AVL
{
int tot;
struct node
{
node *l,*r;
T v;
int h,s,si;
node(T tv){l=r=NULL;v=tv;h=s=si=1;}
node(){l=r=NULL;v=0;h=s=si=1;}
}*Root,f[1000000];
AVL(){Root=NULL;tot=0;}
int height(node *now)
{
return now?now->h:0;
}
int size(node *now)
{
return now?now->s:0;
}
node* includefindindex(node *now,int k)
{
if(k<=size(now->l))return includefindindex(now->l,k);
if(k>size(now->l)+now->si)return includefindindex(now->r,k-(size(now->l)+now->si));
return now;
}
T operator [](int k)
{
return includefindindex(Root,k)->v;
}
node* find(T want)
{
node *tem=Root;
while(tem&&tem->v!=want)
if(tem->v>want)tem=tem->l;
else tem=tem->r;
return tem;
}
int findrank(T want)
{
node *tem=Root;
int t=0;
while(tem)
{
if(tem->v<want)t+=size(tem->l)+tem->si,tem=tem->r;
else if(tem->v>want)tem=tem->l;
else return t+size(tem->l)+1;
}
return 1;
}
node* levo(node *now)
{
node *tem=now->r;
now->r=tem->l;
tem->l=now;
now->h=Max(height(now->l),height(now->r))+1;
now->s=size(now->l)+size(now->r)+now->si;
tem->h=Max(height(tem->l),height(tem->r))+1;
tem->s=size(tem->l)+size(tem->r)+tem->si;
return tem;
}
node* dext(node *now)
{
node *tem=now->l;
now->l=tem->r;
tem->r=now;
now->h=Max(height(now->l),height(now->r))+1;
now->s=size(now->l)+size(now->r)+now->si;
tem->h=Max(height(tem->l),height(tem->r))+1;
tem->s=size(tem->l)+size(tem->r)+tem->si;
return tem;
}
node* lext(node *now)
{
now->l=levo(now->l);
return dext(now);
}
node* devo(node *now)
{
now->r=dext(now->r);
return levo(now);
}
node* balance(node *now)
{
if(height(now->l)==height(now->r)+2)
if(height(now->l->l)>height(now->l->r))now=dext(now);
else now=lext(now);
else if(height(now->r)==height(now->l)+2)
if(height(now->r->r)>height(now->r->l))now=levo(now);
else now=devo(now);
return now;
}
node* findmin(node *now)
{
if(!now)return NULL;
while(now->l)now=now->l;
return now;
}
node* findmax(node *now)
{
if(!now)return NULL;
while(now->r)now=now->r;
return now;
}
node* includeinsert(node *now,T need)
{
if(!now)
{
now=f+(tot++);
now->v=need;
return now;
}
if(need==now->v)++now->si;
else if(need<now->v)now->l=includeinsert(now->l,need);
else now->r=includeinsert(now->r,need);
now->h=Max(height(now->l),height(now->r))+1;
now->s=size(now->l)+size(now->r)+now->si;
return balance(now);
}
node* includeremove(node *now,T need)
{
if(!now)return NULL;
if(now->v>need)now->l=includeremove(now->l,need);
else if(now->v<need)now->r=includeremove(now->r,need);
else if(now->si>1)--now->si;
else if(now->l&&now->r)
{
node* tem=findmin(now->r);
now->v=tem->v;now->si=tem->si;
tem->si=1;
now->r=includeremove(now->r,now->v);
}
else if(now->l||now->r)now=now->l?now->l:now->r;
else return now=NULL;
now->h=Max(height(now->l),height(now->r))+1;
now->s=size(now->l)+size(now->r)+now->si;
return balance(now);
}
node* bigger(T need)
{
node *tem=Root,*ans=NULL;
while(tem)
{
if(tem->v>=need)
{
if(!ans||tem->v<ans->v)ans=tem;
tem=tem->l;
}
else tem=tem->r;
}
return ans;
}
node* lower(T need)
{
node *tem=Root,*ans=NULL;
while(tem)
{
if(tem->v<=need)
{
if(!ans||tem->v>ans->v)ans=tem;
tem=tem->r;
}
else tem=tem->l;
}
return ans;
}
void insert(T need){Root=includeinsert(Root,need);}
void remove(T need){Root=includeremove(Root,need);}
};
因果乃旋转纺车,光彩之多面明镜
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存

浙公网安备 33010602011771号