SBT(Size Balanced Tree平衡树的一种)
2016-07-12 11:04
549 查看
这次要学习平衡树被称为SBT,其全称为Size Balanced Tree,由我国的陈启峰同学所提出。
它是一种高度平衡的二叉树。其基本思想是根据每颗子树的大小,来对二叉树的形态进行调整。
采用s[]数组来记录每颗子树的大小,比如s[T]就表示以T为根节点的子树的节点总数。特别的,如果T为空,那么S[T]=0。
SBT通过两个性质来保证树的平衡性:
简单来说,即满足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个整数,表示针对询问的回答,保证一定有合法的解
样例输入
样例输出
它是一种高度平衡的二叉树。其基本思想是根据每颗子树的大小,来对二叉树的形态进行调整。
采用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; }
相关文章推荐
- 事务的隔离等级 (ANSI标准)
- HBuild Hybrid App开发(十一)二维码生成
- HDFS理论及基本命令
- c# UDP广播
- Light oj 1074 - Extended Traffic
- php的四种基本算法
- FFMPEG采集摄像头数据并切片为iPhone的HTTP Stream流
- 07.12C
- pthread_create主线程与创建的新线程之间退出关系
- 栈溢出攻击
- 基于python的selenium实现警告框的处理
- ECMAScript 6 学习系列课程 (ES6 Promise对象的使用)
- 深入解析线程池的使用
- ..
- apache commons fileupload 发行审查工具结果(2016-07-01更新)
- android 设置 永不休眠
- 关于cad生成dwf文件和插入dwf快
- hadoop2.4+spark1.3.0集群安装
- Java之下载word文档
- 在Mac下配置:Apache+php+MySql