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的顺序插入到二叉排序树中,那么二叉排序树就 ...
随机推荐
- C语言 · 三个整数的排序
算法提高 三个整数的排序 时间限制:1.0s 内存限制:256.0MB 问题描述 输入三个数,比较其大小,并从大到小输出. 输入格式 一行三个整数. 输出格式 一行三个整数,从大到小 ...
- java资料——线性表(转)
线性表 线性表(亦作顺序表)是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的.线性表的逻辑结构简单, ...
- OpenWRT中的按键和灯的GPIO控制实现
基于BarrierBreaker版本,基于AR9331 AP121 Demo单板 来进行描述 1.灯 A.在mach-ap121.c中,定义了灯所对应的GPIO定义: #define AP121_GP ...
- 【SpringMVC笔记】第一课-框架执行过程
SpringMVC模型的执行流程
- 数据结构——算法之(043)(c++各种排序算法实现)
[申明:本文仅限于自我归纳总结和相互交流,有纰漏还望各位指出. 联系邮箱:Mr_chenping@163.com] 题目: c++ 各种排序算法实现 题目分析: 详细排序原理參考相关算法书籍 算法实现 ...
- Spring 中三种Bean配置方式比较
今天被问到Spring中Bean的配置方式,很尴尬,只想到了基于XML的配置方式,其他的一时想不起来了,看来Spring的内容还没有完全梳理清楚,见到一篇不错的文章,就先转过来了. 以前Java框架基 ...
- CentOS安装ssh服务
yum search ssh yum install openssh-server service sshd status [编辑]艺搜参考 http://www.cnblogs.com/eastso ...
- table获取checkbox是否选中的几种方法
function test() { $(".table tbody tr").find("td:first input:checkbox").each(func ...
- json拼接转义符
//转义符替 function escapeReplace(Str) { var newStrJson = Str.replace(/\%/g, "%25"); newStrJso ...
- jquery 自动完成 Autocomplete插件汇总
1. jQuery Autocomplete Mod jQuery Autcomplete插件.能够限制下拉菜单显示的结果数. 主页:http://www.pengoworks.com/worksho ...