平衡二叉树SBT模板

最近开始学习SBT,参考陈启峰的论文,具体的证明没有看,弱菜只是会用。。。

SBT有两条性质:

对于SBT中的每个结点t,有性质(a)(b)

(a). s[right[t]]≥s[left[left[t]]],s[right[left[t]]]

(b). s[left[t]]≥s[right[right[t]]],s[left[right[t]]]

《平衡二叉树SBT模板》

 

即在上图中,有s[A],s[B]≤s[R]&s[C],s[D] ≤s[L]

可以参考下面的博客,平衡二叉树SBT


关于删除操作的说明:

与普通维护size域的BST删除相同。
关于无需Maintain的说明by sqybi:
在删除之前,可以保证整棵树是一棵SBT。当删除之后,虽然不能保证这棵树还是SBT,但是这时整棵树的最大深度并没有改变,所以时间复杂度也不会增加。这时,Maintain就显得是多余的了。


下面是模板:

struct SBT
{
    int left,right,size,key;
    void init(int val)
    {
        left=right=0;
        size=1;
        key=val;
    }
}tree[maxn];
int tot,root;
void left_rotate(int &x)
{
    int y=tree[x].right;
    tree[x].right=tree[y].left;
    tree[y].left=x;
    tree[y].size=tree[x].size;
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    x=y;
}
void right_rotate(int &x)
{
    int y=tree[x].left;
    tree[x].left=tree[y].right;
    tree[y].right=x;
    tree[y].size=tree[x].size;
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    x=y;
}
void maintain(int &x,int flag)
{
    if(!flag)
    {
        if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)
            right_rotate(x);
        else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)
            left_rotate(tree[x].left),right_rotate(x);
        else return;
    }
    else
    {
        if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)
            left_rotate(x);
        else if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)
            right_rotate(tree[x].right),left_rotate(x);
        else return;
    }
    maintain(tree[x].left,0);
    maintain(tree[x].right,1);
    maintain(x,0);
    maintain(x,1);
}
//插入值为key的节点
void insert(int &x,int key)
{
    if(!x)
    {
        x=++tot;
        tree[x].init(key);
    }
    else
    {
        tree[x].size++;
        if(key<tree[x].key)insert(tree[x].left,key);
        else insert(tree[x].right,key);
        maintain(x,key>=tree[x].key);
    }
}
//删除值为key的节点
int del(int &x,int key)
{
    if(!x)return 0;
    tree[x].size--;
    if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)||
       (key>tree[x].key&&tree[x].right==0))
    {
        if(tree[x].left&&tree[x].right)
        {
            int p=del(tree[x].left,key+1);
            tree[x].key=tree[p].key;
            return p;
        }
        else
        {
            int p=x;
            x=tree[x].left+tree[x].right;
            return p;
        }
    }
    else
        return del(key<tree[x].key?tree[x].left:tree[x].right,key);
}
//int del(int &x,int key)
//{
//    if(!x)return 0;
//    int res=0;
//    tree[x].size--;
//    if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)||
//       (key>tree[x].key&&tree[x].right==0))
//    {
//        if(tree[x].left&&tree[x].right)
//        {
//            int p=del(tree[x].left,key+1);
//            tree[x].key=tree[p].key;
//            res=p;
//        }
//        else
//        {
//            int p=x;
//            x=tree[x].left+tree[x].right;
//            res=p;
//        }
//    }
//    else
//        res=del(key<tree[x].key?tree[x].left:tree[x].right,key);
//    maintain(x,key<tree[x].key);
//    return res;
//}
//返回值v的前驱的值,如果没有前驱返回v本身
int Pred(int t,int v)
{
    if(!t)return v;
    if(v<=tree[t].key)return Pred(tree[t].left,v);
    else
    {
        int tmp=Pred(tree[t].right,v);
        return v==tmp?tree[t].key:tmp;
    }
}
//返回值v的后继的值,如果没有后继返回v本身
int Succ(int t,int v)
{
    if(!t)return v;
    if(v>=tree[t].key)return Succ(tree[t].right,v);
    else
    {
        int tmp=Succ(tree[t].left,v);
        return v==tmp?tree[t].key:tmp;
    }
}
//返回值val的前驱的编号,没有的话,返回y
int get_pre(int &r,int y,int val)
{
    if(r==0)return y;
    if(val>tree[r].key)//加上等号就是大于等于
        return get_pre(tree[r].right,r,val);
    else return get_pre(tree[r].left,y,val);
}
//返回值val的后继的编号,没有的话,返回y
int get_next(int &r,int y,int val)
{
    if(r==0)return y;
    if(val<tree[r].key)return get_next(tree[r].left,r,val);
    else return get_next(tree[r].right,y,val);
}
//查找是否存在值为val的节点
int find(int r,int val)
{
    if(r&&val!=tree[r].key)
        r=(val<tree[r].val?find(tree[r].left,val):find(tree[r].right,val));
    return r;
}
//得到第k大元素的值
int get_kth(int &x,int k)
{
    if(k<=tree[tree[x].left].size)
        return get_kth(tree[x].left,k);
    if(k>tree[tree[x].left].size+1)
        return get_kth(tree[x].right,k-tree[tree[x].left].size-1);
    return tree[x].key;//改一下就可以返回节点编号了
}
//返回根为x的树最大值的编号
int get_max(int x)
{
    while(tree[x].right)x=tree[x].right;
    return x;
}
//返回根为x的树最小值的编号
int get_min(int x)
{
    while(tree[x].left)x=tree[x].left;
    return x;
}
//返回值val的排名
int get_rank(int &r,int val)
{
    if(val<tree[r].val)
        return get_rank(tree[r].left,val);
    else if(val>tree[r].val)
        return get_rank(tree[r].right,val)+tree[tree[r].left].size+1;
    return tree[tree[r].left].size+1;
}

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/u010660276/article/details/43704709
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞