您的位置:首页 > 其它

SBT(Size Balanced Tree平衡树的一种)

2016-07-12 11:04 549 查看
这次要学习平衡树被称为SBT,其全称为Size Balanced Tree,由我国的陈启峰同学所提出。

它是一种高度平衡的二叉树。其基本思想是根据每颗子树的大小,来对二叉树的形态进行调整。

采用s[]数组来记录每颗子树的大小,比如s[T]就表示以T为根节点的子树的节点总数。特别的,如果T为空,那么S[T]=0。

SBT通过两个性质来保证树的平衡性:
s[T.right]≥s[T.left.left],s[T.left.right]
s[T.left]≥s[T.right.right],s[T.right.left]




简单来说,即满足s[R]≥s[A],s[B],同时s[L]≥s[C],S[D]。也就是说每个子树的大小大于所有侄子的大小。

同样的,SBT通过旋转来动态调整树的结构,在SBT中采用以根为参数的旋转函数。

当我们在SBT中插入或者删除一个节点时,以上两个性质可能会被破坏。这时需要使用maintain函数来对树的形态进行修正。

当我们执行maintain(T)时,需要保证子树T.left和T.right已经满足SBT的两条性质。这时对于T来说一共有4种情况。(详细见下面代码)

例题:


输入

第1行:1个正整数n,表示操作数量,10≤n≤100,000
第2..n+1行:每行1个字母c和1个整数k:
若c为'I',表示插入一个数字k到树中,-1,000,000,000≤k≤1,000,000,000
若c为'Q',表示询问树中第k小数字,保证1≤k≤树的节点数量


输出

若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解

样例输入
5
I 3
I 2
Q 1
I 5
Q 2


样例输出
2
3

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

//平衡树size balanced tree

struct node
{
node(int k,node* n)
{
father = n;
left = right = NULL;
key = k;
sumNodes = 1;//以自己为根所有节点个数,包括自己
}
int key, sumNodes;
node *father, *left, *right;
}*root;

void left_rotate(node* a)
{
if (a != NULL)
{
node* k = a->right;
if (k != NULL)
{
a->right = k->left;
if (k->left)
k->left->father = a;

k->left = a;
if (a->father == NULL)
root = k;
else
{
if (a->father->left == a)
a->father->left = k;
else
a->father->right = k;
}
k->father = a->father;
a->father = k;
k->sumNodes = a->sumNodes;

int sumleft = 0, sumright = 0;
if (a->left)
sumleft = a->left->sumNodes;
if (a->right)
sumright = a->right->sumNodes;
a->sumNodes = sumleft + sumright + 1;
}
}
}

void right_rotate(node* a)
{
if (a != NULL)
{
node* k = a->left;
if (k != NULL)
{
a->left = k->right;
if (k->right)
k->right->father = a;

k->right = a;
if (a->father == NULL)
root = k;
else
{
if (a->father->left == a)
a->father->left = k;
else
a->father->right = k;
}
k->father = a->father;
a->father = k;
k->sumNodes = a->sumNodes;

int sumleft = 0, sumright = 0;
if (a->left)
sumleft = a->left->sumNodes;
if (a->right)
sumright = a->right->sumNodes;
a->sumNodes = sumleft + sumright + 1;
}
}
}

void maintain(node* n, bool flag)
{
if (n == NULL) return;
if (flag == false)
{
if (n->left)
{
if (n->left->left && (!(n->right) || n->left->left->sumNodes > n->right->sumNodes))
right_rotate(n);
else if (n->left->right && (!(n->right) || n->left->right->sumNodes > n->right->sumNodes))
{
left_rotate((n->left));
right_rotate(n);
}
else return;
}
else return;
}
else
{
if (n->right)
{
if (n->right->right && (!(n->left) || n->right->right->sumNodes > n->left->sumNodes))
left_rotate(n);
else if (n->right->left && (!(n->left) || n->right->left->sumNodes > n->left->sumNodes))
{
right_rotate((n->right));
left_rotate(n);
}
else return;
}
else return;
}
maintain(n->left, false);
maintain(n->right, true);
maintain(n, false);
maintain(n, true);
}

void bst_insert(node* n, int key)
{
n->sumNodes = n->sumNodes + 1;
if (key < n->key)
{
if (n->left == NULL)
n->left = new node(key, n);
else
bst_insert(n->left, key);
}
else
{
if (n->right == NULL)
n->right = new node(key, n);
else
bst_insert(n->right, key);
}
maintain(n, key >= n->key);
}

void insert(int key)
{
if (root == NULL)
root = new node(key, NULL);
else
bst_insert(root, key);
}

int Q(node* n, int k)
{
if (k > n->sumNodes)
return -1;//不会出现
if (n->left != NULL)
{
int num = n->left->sumNodes + 1;
if (k == num)
return n->key;
else if (k < num)
return Q(n->left, k);
else if (k > num)
return Q(n->right, k - num);
}
else if (n->right != NULL)
{
if (k == 1)
return n->key;
else
return Q(n->right, k - 1);
}
else
return n->key;
}

void print(node* r) {
if (r == NULL) {
printf("null\n");
return;
}
printf("%d\n", r->key);
printf("left ");
print(r->left);
printf("right ");
print(r->right);
}

int main()
{
int n, k;
char c;
cin >> n;
while (n--)
{
cin >> c >> k;
if (c == 'I')
insert(k)//, print(root);
else if (c == 'Q')
cout << Q(root, k) << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: