[轉載] SBT(Size Balanced Tree)

/************************************************* 
數據結構: 
SBT(Size Balanced Tree),又稱傻逼樹; 
 
數據域: 
值域key,左孩子left,右孩子right,保持平衡的size; 
 
性質: 
每棵子樹的大小不小於其兄弟的子樹大小; 
 
插入: 
插入算法先簡單插入節點,然後調用一個維護過程以保持性質; 
 
刪除: 
刪除操作與普通維護size域的二叉查找樹相同; 
 
最大值和最小值: 
由於SBT本身已經維護了size域; 
所以只需用Select(T,1)來求最大值; 
Select(T,T.size)求最小值; 
其中Select(T,k)函數返回樹T在第k位置上的節點值; 
**************************************************/  
#include<iostream>  
#include<cstring>  
#include<cstdlib>  
#include<cstdio>  
#include<climits>  
#include<algorithm>  
using namespace std;  
  
const int N = 100000;  
int key[N], lefts[N], rights[N], size[N];  
int u;//根結點  
int node;  
  
inline void Left_Rotate(int &x)  
{  
    int k = rights[x];  
    rights[x] = lefts[k];  
    lefts[k] = x;  
    size[k] = size[x];  
    size[x] = size[lefts[x]] + size[rights[x]] + 1;  
    x = k;  
}  
  
inline void Right_Rotate(int &y)  
{  
    int k = lefts[y];  
    lefts[y] = rights[k];  
    rights[k] = y;  
    size[k] = size[y];  
    size[y] = size[lefts[y]] + size[rights[y]] + 1;  
    y = k;  
}  
  
void Maintain(int &u, bool flag)//維護  
{  
    if(flag == false)  
    {  
        if(size[lefts[lefts[u]]] > size[rights[u]])  
            Right_Rotate(u);  
        else  
        {  
            if(size[rights[lefts[u]]] > size[rights[u]])  
            {  
                Left_Rotate(lefts[u]);  
                Right_Rotate(u);  
            }  
            else return;  
        }  
    }  
    else  
    {  
        if(size[rights[rights[u]]] > size[lefts[u]])  
            Left_Rotate(u);  
        else  
        {  
            if(size[lefts[rights[u]]] > size[lefts[u]])  
            {  
                Right_Rotate(rights[u]);  
                Left_Rotate(u);  
            }  
            else return;  
        }  
    }  
    Maintain(lefts[u], false);  
    Maintain(rights[u], true);  
    Maintain(u, true);  
    Maintain(u, false);  
}  
  
void Insert(int &u, int v)//插入結點  
{  
    if(u == 0)  
    {  
        key[u = ++node] = v;  
        size[u] = 1;  
    }  
    else  
    {  
        size[u]++;  
        if(v < key[u])  
            Insert(lefts[u], v);  
        else  
            Insert(rights[u], v);  
        Maintain(u, v >= key[u]);  
    }  
}  
  
int Delete(int &u, int v)//刪除結點  
{  
    size[u]--;  
    if( (v == key[u]) || (v < key[u] && lefts[u] == 0) || (v > key[u] && rights[u] == 0) )  
    {  
        int r = key[u];  
        if(lefts[u] == 0 || rights[u] == 0)  
            u = lefts[u] + rights[u];  
        else  
            key[u] = Delete(lefts[u], key[u] + 1);  
        return r;  
    }  
    else  
    {  
        if(v < key[u])  
            return Delete(lefts[u], v);  
        else  
            return Delete(rights[u], v);  
    }  
}  
  
int Search(int x, int k)//查詢  
{  
    if(x == 0 || k == key[x])  
        return x;  
    if(k < key[x])  
        return Search(lefts[x], k);  
    else  
        return Search(rights[x], k);  
}  
  
int Select(int u, int k)//返回樹在第k位置上的結點值  
{  
    int r = size[lefts[u]] + 1;  
    if(k == r)  
        return key[u];  
    else if(k < r)  
        return Select(lefts[u], k);  
    else  
        return Select(rights[u], k - r);  
}  
  
int Successor(int u, int k)//查詢結點k的後繼  
{  
    if(u == 0)  
        return k;  
    if(key[u] <= k)  
        return Successor(rights[u], k);  
    else  
    {  
        int r = Successor(lefts[u], k);  
        if(r == k)  
            return key[u];  
        else  
            return r;  
    }  
}  
  
int Predecessor(int u, int k)//查詢結點k的前驅  
{  
    if(u == 0)  
        return k;  
    if(key[u] >= k)  
        return Predecessor(lefts[u], k);  
    else  
    {  
        int r = Predecessor(rights[u], k);  
        if(r == k)  
            return key[u];  
        else  
            return r;  
    }  
}  
  
int Rank(int u, int k)//排名(rank),也叫秩,求整棵樹中從大到小排序的第k位元素;  
{  
    if(u==0)  
        return 1;  
    if(key[u] >= k)  
        return Rank(lefts[u], k);  
    else  
        return size[lefts[u]] + Rank(rights[u], k) + 1;  
}  
  
int main()  
{  
    freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);  
    int n;  
    scanf("%d",&n);  
    for(int i=0; i<n; i++)  
    {  
        int cmd,x;  
        scanf("%d%d",&cmd,&x);  
        switch(cmd)  
        {  
        case 1:  
            Insert(u,x);  
            break;  
        case 2:  
            Delete(u,x);  
            break;  
        case 3:  
            printf("%d\n", Search(u,x));  
            break;  
        case 4:  
            printf("%d\n", Rank(u,x));  
            break;  
        case 5:  
            printf("%d\n", Select(u,x));  
            break;  
        case 6:  
            printf("%d\n", Predecessor(u,x));  
            break;  
        case 7:  
            printf("%d\n", Successor(u,x));  
            break;  
        }  
    }  
    return 0;  
}  

發佈了90 篇原創文章 · 獲贊 33 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章