平衡树-SBT

SBT 

Size Balabce Tree

SBT的平衡条件是,对于一个节点,他的size必须大于等于他的兄弟的左右儿子的size

不满足的话,就要进行修复操作,即maintain操作

加入我们现在修复的是T[x].son[1],

如果T[T[T[x].son[0]].son[0]].size > T[T[x].son[1]].size 直接将x右旋 (即兄弟的左子树的size)

如果T[T[T[x].son[0]].son[1]].size > T[T[x].son[1]].size 先将T[x].son[0]左旋,再将x右旋

最后我们在重新修复x以及左右儿子

以poj 3481为例 代码如下

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int MAXN = 1000006;
int cnt, root;
struct Tree
{
    int key, size, son[2] , num;
}T[MAXN];
inline void PushUp(int x)
{
    T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+1;
}
inline int Newnode(int key , int num)
{
    ++cnt;
    T[cnt].key=key;
    T[cnt].num=num;
    T[cnt].size=1;
    T[cnt].son[0]=T[cnt].son[1]=0;
    return cnt;
}
void Rotate(int p, int &x)
{
    int y=T[x].son[!p];
    T[x].son[!p]=T[y].son[p];
    T[y].son[p]=x;
    PushUp(x);
    PushUp(y);
    x=y;
}
void Maintain(int &x, int p) //维护SBT的!p子树
{
    if(T[T[T[x].son[p]].son[p]].size > T[T[x].son[!p]].size)
        Rotate(!p, x);
    else if(T[T[T[x].son[p]].son[!p]].size > T[T[x].son[!p]].size)
        Rotate(p, T[x].son[p]), Rotate(!p, x);
    else return;
    Maintain(T[x].son[0], 0);
    Maintain(T[x].son[1], 1);
    Maintain(x, 0);
    Maintain(x, 1);
}
inline int Prev() //返回比根值小的最大值 若无返回0
{
    int x=T[root].son[0];
    if(!x) return 0;
    while(T[x].son[1])
        x=T[x].son[1];
    return x;
}
inline int Succ() //返回比根值大的最小值 若无返回0
{
    int x=T[root].son[1];
    if(!x) return 0;
    while(T[x].son[0])
        x=T[x].son[0];
    return x;
}
void Inseroot(int key, int &x, int num)
{
    if(!x) x=Newnode(key , num);
    else
    {
        T[x].size++;
        Inseroot(key, T[x].son[key > T[x].key],num);
        Maintain(x, key > T[x].key);
    }
}
bool Delete(int key, int &x) //删除值为key的节点 key可以不存在
{
    if(!x) return 0;
    if(T[x].key == key)
    {
        if(!T[x].son[0])
        {
            x=T[x].son[1];
            return 1;
        }
        if(!T[x].son[1])
        {
            x=T[x].son[0];
            return 1;
        }
        int y=Prev();
        T[x].size--;
        return Delete(T[x].key, T[x].son[0]);
    }
    else
        if(Delete(key, T[x].son[key > T[x].key]))
        {
            T[x].size--;
            return 1;
        }
}
int GetPth(int p, int &x) //返回第p小的节点
{
    if(!x) return 0;
    if(p == T[T[x].son[0]].size+1)
        return x;
    if(p > T[T[x].son[0]].size+1)
        return GetPth(p-T[T[x].son[0]].size-1, T[x].son[1]);
    else
        return GetPth(p, T[x].son[0]);
}
int GetRank(int key, int &x) //找出值<=key的节点个数
{
    if(!x) return 0;
    if(T[x].key <= key)
        return T[T[x].son[0]].size+1+GetRank(key, T[x].son[1]);
    else
        return GetRank(key, T[x].son[0]);
}
int solve(int x , int p)
{
    if(x == 0)
        return 0;
    while( T[x].son[p] )
    {
        x = T[x].son[p];
    }
    return x;
}
int main()
{
    int flag ,num , key;
    while( scanf("%d" , &flag) != EOF )
    {
        if(flag == 0)
            break;
        if(flag == 1)
        {
            scanf("%d%d" , &num , &key);
            Inseroot(key , root , num);
        }
        if(flag == 2)
        {
            int tmp = solve(root , 1);
            if(tmp == 0)
                printf("0\n");
            else
            {
                printf("%d\n" ,T[tmp].num);
                Delete(T[tmp].key , root);
            }
        }
        if(flag == 3)
        {
            int tmp = solve(root , 0);
            if(tmp == 0)
                printf("0\n");
            else
            {
                printf("%d\n" , T[tmp].num);
                Delete(T[tmp].key , root);
            }
        }
    }
}

至此~~  再看一看我的主席树模板就不看数据结构了  当初是为什么就学习了主席树呢  真是忘记了

posted @ 2018-10-17 19:55  Flower_Z  阅读(479)  评论(0编辑  收藏  举报