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的顺序插入到二叉排序树中,那么二叉排序树就 ...
随机推荐
- 【Unity笔记】物体朝着鼠标位置移动
其实思路也很简单,就是先获取到鼠标的坐标,然后赋值给目标物体即可. void Update(){ // 物体跟随鼠标移动 Vector2 mousePos = Input.mousePosition; ...
- C语言 · 淘淘的名单
算法提高 淘淘的名单 时间限制:100ms 内存限制:8.0MB 问题描述 by ZBY... :) 淘淘拿到了一份名单,他想对上面的名字进行处理,挑出一些特殊的名字,他请你来帮忙. ...
- 一站式学习Wireshark(十):应用Wireshark显示过滤器分析特定数据流(下)
介绍 掌握显示过滤器对于网络分析者来说是一项必备的技能.这是一项大海捞针的技巧.学会构建,编辑,保存关键的显示过滤器能够节省数小时的时间. 与捕捉过滤器使用的BPF语法不同,显示过滤器使用的是Wire ...
- 试验如何通过审核Google AdSense——我跟谷歌ads杠上啦
http://www.hankcs.com/appos/webhost/apply-google-ads.html —————————————————————————————————————————— ...
- 为iframe添加鼠标事件
1.关于iframe标签 使用iframe元素会创建包含另外一个文档的内联框架(即行内框架).所以我们可以使用iframe标签,在一个页面嵌入另一个页面.通过指定iframe的src为另一个页面的路径 ...
- 【转】Jmeter分布式压力测试
安装 下载地址:http://jmeter.apache.org/download_jmeter.cgi 安装前提(因为jmeter依赖于Java所以必须先配置好java) 下载后解压: tar -x ...
- Python 变量类型和运算符
-*- coding:utf-8 -*- ''' if语法 if conditon: [tab键] command [tab键] command ... else: [tab键] command [t ...
- 使用ffmpeg获取视频流后如何封装存储成mp4文件
int main(int argc,char *argv[]) 02 { 03 AVFormatContext *pFormatCtx; 04 int i,videoStream; 05 AVC ...
- 高速入门:十分钟学会Python
初试牛刀 如果你希望学习Python这门语言.却苦于找不到一个简短而全面的新手教程.那么本教程将花费十分钟的时间带你走入Python的大门.本文的内容介于教程(Toturial)和速查手冊(Cheat ...
- zookeeper_process内存泄露问题
单线程模式下,不能递归调用zookeeper_process函数,否则会造成内存泄露. 下列图是在watcher中调用zookeeper_process时,用valgrind检测到的情况: