Size Balanced Tree
Size Balanced Tree(SBT)是目前速度最快的平衡二叉搜索树,且能够进行多种搜索操作,区间操作;和AVL、红黑树、伸展树、Treap类似,SBT也是通过对节点的旋转来维持树的平衡,而相比其他平衡树,SBT维持平衡所需要的额外数据很少,只需要维持以当前节点为根的子树的大小;且SBT的编写复杂度低。因此具有空间优势、速度优势、编写优势。
SBT的节点
SBT节点维持很少的额外信息,只需要知道以当前节点为根的子树的大小。
struct TreeNode{
int data;
TreeNode* child[2];
int size; //以该节点为根的子树的大小(节点的个数)
TreeNode(int d){
data = d;
child[0] = child[1] = NULL;
size = 1;
}
};
SBT的平衡性质
一棵平衡的SBT树满足如下要求:
记S[t]为以节点t为根的子树的大小,则对于每个节点T,记其左子节点L, 右子节点R, 左子结点的左子结点LL, 左子结点的右子节点LR, 右子节点的左子结点RL, 右子节点的右子节点RR。
则有, S[L] >= max(S[RL], S[RR]), S[R] >= max(S[LL], S[LR]).
即任何一个节点的size均大于等于其侄子节点的size。 (侄子节点:定义为一个节点的兄弟节点的两个子节点)
SBT的维护操作
一棵平衡的SBT在进行插入和删除之后,可能会不再平衡,此时需要进行维护操作,维护操作需要进行左旋或者右旋操作,旋转操作和其他平衡树的旋转类似(具体见zig-zag旋转) .
SBT的非平衡情况分为两类:左子结点和左子结点的侄子节点不平衡或者右子节点和右子节点的侄子节点不平衡。这里以右子节点和右子节点的侄子节点为例,进行Maintain操作。
失衡情形1: S[LL] > S[R]
(1)执行 RightRotate(T),得到如下结果
(2)此时以T为根的树可能不平衡,递归调用Maintain(T)
(3)此时T成为平衡SBT, 再次对L调用Maintain(L)将整体变为平衡SBT
失衡情形2: S[LR] > S[R]
(1)执行 LeftRotate(L),得到如下结果
(2)执行 RightRotate(T),得到如下结果
(2)此时以B和R为根的树可能不平衡,递归调用Maintain(B)、Maintain(R)
(3)此时T成为平衡SBT, 再次对L调用Maintain(L)将整体变为平衡SBT
由于Maintain操作是个递归执行的函数,貌似可能会出现无限循环,但实际上,陈启峰在论文里分析过了,Maintain操作的平坦复杂度为O(1)。因此Maintain操作不会出现无法结束的情况。
SBT的其他操作
和其他的二叉搜索树一样,SBT支持插入、删除、查找等操作。插入和删除操作可能会破坏SBT的平衡性质,因此,需要在普通的插入和删除之后对节点进行维护,即调用Maintain函数。
实现(c++)
#include<iostream>
using namespace std;
struct TreeNode{
int data;
TreeNode* child[2];
int size;
int count;
TreeNode(int d){
data = d;
child[0] = child[1] = NULL;
size = count = 1;
}
void Update(){
size = count;
if (child[0]){
size += child[0]->size;
}
if (child[1]){
size += child[1]->size;
}
}
};
struct SBT{
TreeNode* root;
SBT() :root(NULL){}; void Rotate(TreeNode*& node, int dir){
TreeNode* ch = node->child[dir];
node->child[dir] = ch->child[!dir];
ch->child[!dir] = node;
node = ch;
}
//返回node节点为根的子树的大小
int GetSize(TreeNode* node){
if (node)
return node->size;
return 0; //对于空节点,直接返回0
} //维持平衡
void Maintain(TreeNode*& node, bool flag){
TreeNode* R = node->child[1];
TreeNode* L = node->child[0];
TreeNode* LL = NULL,*LR = NULL,*RL = NULL,*RR = NULL;
if (L){
LL = L->child[0];
LR = L->child[1];
}
if (R){
RL = R->child[0];
RR = R->child[1];
} if (flag == false){ //左边维护
if (GetSize(LL) > GetSize(R)){ //失衡情况1
Rotate(node, 0);
}
else if (GetSize(LR) > GetSize(R)){ //失衡情况2
Rotate(L, 1);
Rotate(node, 0);
}
else{
return; //不失衡,直接返回
}
}
else{
if (GetSize(RR) > GetSize(L)){
Rotate(node, 1);
}
else if (GetSize(RL) > GetSize(L)){
Rotate(R, 0);
Rotate(node, 1);
}
else
{
return;
}
}
Maintain(node->child[0], false); //继续将 左子树维持平衡,注意这里不能直接使用L,因为之前进行了旋转操作
Maintain(node->child[1], true); //继续将 右子树维持平衡
Maintain(node, true); //再维持 node
Maintain(node, false);
} void Insert(TreeNode*& node, int data){
if (!node){
node = new TreeNode(data);
return;
}
else if (node->data == data){
node->count++;
node->Update(); //更新本节点以及其祖先节点的size
return;
}
else {
int dir = node->data < data;
Insert(node->child[dir], data); Maintain(node, ! dir);
//如果新插入的数据 小于 当前节点的数据,则被插入左子树,
//此时左子树的左右子节点的size可能大于右子节点,因此Maintain(x, false) node->Update();
}
} void Delete(TreeNode*& node, int w){
if (!node){
return;
}
if (node->data == w){
if (node->child[0] && node->child[1]){
TreeNode* succ = node->child[1];
while (succ->child[0]){
succ = succ->child[0];
}
node->data = succ->data;
succ->data = w;
Delete(node, w);
}
else{
TreeNode* tmp_node = NULL;
if (node->child[0])
tmp_node = node->child[0];
else
tmp_node = node->child[1];
delete node;
node = tmp_node;
}
}
Maintain(node, false);
node->Update();
} };
参考:
SBT-陈启峰
Size Balanced Tree的更多相关文章
- Size Balanced Tree(SBT) 模板
首先是从二叉搜索树开始,一棵二叉搜索树的定义是: 1.这是一棵二叉树: 2.令x为二叉树中某个结点上表示的值,那么其左子树上所有结点的值都要不大于x,其右子树上所有结点的值都要不小于x. 由二叉搜索树 ...
- C基础 - 终结 Size Balanced Tree
引言 - 初识 Size Balanced Tree 最近在抽细碎的时间看和学习 random 的 randnet 小型网络库. iamrandom/randnet - https://github. ...
- Size Balanced Tree(SBT树)整理
不想用treap和Splay,那就用SB树把,哈哈,其实它一点也SB,厉害着呢. 先膜拜一下作者陈启峰.Orz 以下内容由我搜集整理得来. 一.BST及其局限性 二叉查找树(Binary Search ...
- 初学 Size Balanced Tree(bzoj3224 tyvj1728 普通平衡树)
SBT(Size Balance Tree), 即一种通过子树大小(size)保持平衡的BST SBT的基本性质是:每个节点的size大小必须大于等于其兄弟的儿子的size大小: 当我们插入或者删除一 ...
- 子树大小平衡树(Size Balanced Tree,SBT)操作模板及杂谈
基础知识(包括但不限于:二叉查找树是啥,SBT又是啥反正又不能吃,平衡树怎么旋转,等等)在这里就不(lan)予(de)赘(duo)述(xie)了. 先贴代码(数组模拟): int seed; int ...
- Size Balanced Tree(节点大小平衡树)
定义 SBT也是一种自平衡二叉查找树,它的平衡原理是每棵树的大小不小于其兄弟树的子树的大小 即size(x->l)$\ge$size(x->r->l),size(x->r-&g ...
- Size Balance Tree(SBT模板整理)
/* * tree[x].left 表示以 x 为节点的左儿子 * tree[x].right 表示以 x 为节点的右儿子 * tree[x].size 表示以 x 为根的节点的个数(大小) */ s ...
- 56. 2种方法判断二叉树是不是平衡二叉树[is balanced tree]
[本文链接] http://www.cnblogs.com/hellogiser/p/is-balanced-tree.html [题目] 输入一棵二叉树的根结点,判断该树是不是平衡二叉树.如果某二叉 ...
- 重学数据结构系列之——平衡树之SB Tree(Size Blanced Tree)
学习来源:计蒜客 平衡树 1.定义 对于每一个结点.左右两个子树的高度差的绝对值不超过1,或者叫深度差不超过1 为什么会出现这样一种树呢? 假如我们依照1-n的顺序插入到二叉排序树中,那么二叉排序树就 ...
随机推荐
- Nginx_lua缓存问题,关闭lua_code_cache
打开nginx.conf配置server{ lua_code_cache off; //关闭lua缓存 重启后生效 server_name localhost; default_type 'text/ ...
- [LintCode]计算两个数的交集(一)
问题分析: 既然返回值没有重复,我们不妨将结果放进set中,然后对两个set进行比较. 问题求解: public class Solution { /** * @param nums1 an inte ...
- Mac下删除安装的pkg
Mac下的安装和删除都比windows更加简单清晰,这点在dmg方式下非常明显,但很多时候我们会使用pkg来进行安装,这样的安装想删除就有点麻烦了. 比如,我安装了Golang这个pkg用于g ...
- 聊聊Javascript中的AOP编程
Duck punch 我们先不谈AOP编程,先从duck punch编程谈起. 如果你去wikipedia中查找duck punch,你查阅到的应该是monkey patch这个词条.根据解释,Mon ...
- Session和几种状态保持方案理解
一.术语session 在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相同的. session, ...
- cutadapt 的安装与使用
cutadapt 是一款质量过滤的软件, 它可以删除adapter, primer. polyA尾等序列:也可以用来去除低质量序列 源代码: https://github.com/marcelm/cu ...
- Unity3D之碰撞体,刚体
一 概念介绍 刚体 Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动.任何游戏对象只有添加了刚体组件才能受到重力的影 ...
- php中ignore_user_abort函数的用法(定时)
PHP中的ignore_user_abort函数是当用户关掉终端后脚本不停止仍然在执行,可以用它来实现计划任务与持续进程,下面会通过实例讨论ignore_user_abort()函数的作用与用法. i ...
- 深入new/delete:Operator new的全局重载
Operator new 的全局重载 原文地址:http://blog.csdn.net/zhenjing/article/details/4354880 我们经常看到这么一句话: operator ...
- [译]Unity3D内存管理——对象池(Object Pool)
原文地址:C# Memory Management for Unity Developers (part 3 of 3), 其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身 ...