平衡二叉树SBT模板
2015-02-10 16:38
330 查看
最近开始学习SBT,参考陈启峰的论文,具体的证明没有看,弱菜只是会用。。。
SBT有两条性质:
对于SBT中的每个结点t,有性质(a)(b):
(a). s[right[t]]≥s[left[left[t]]],s[right[left[t]]]
(b). s[left[t]]≥s[right[right[t]]],s[left[right[t]]]
即在上图中,有s[A],s[B]≤s[R]&s[C],s[D] ≤s[L]
可以参考下面的博客,平衡二叉树SBT
关于删除操作的说明:
与普通维护size域的BST删除相同。
关于无需Maintain的说明by sqybi:
在删除之前,可以保证整棵树是一棵SBT。当删除之后,虽然不能保证这棵树还是SBT,但是这时整棵树的最大深度并没有改变,所以时间复杂度也不会增加。这时,Maintain就显得是多余的了。
下面是模板:
SBT有两条性质:
对于SBT中的每个结点t,有性质(a)(b):
(a). s[right[t]]≥s[left[left[t]]],s[right[left[t]]]
(b). s[left[t]]≥s[right[right[t]]],s[left[right[t]]]
即在上图中,有s[A],s[B]≤s[R]&s[C],s[D] ≤s[L]
可以参考下面的博客,平衡二叉树SBT
关于删除操作的说明:
与普通维护size域的BST删除相同。
关于无需Maintain的说明by sqybi:
在删除之前,可以保证整棵树是一棵SBT。当删除之后,虽然不能保证这棵树还是SBT,但是这时整棵树的最大深度并没有改变,所以时间复杂度也不会增加。这时,Maintain就显得是多余的了。
下面是模板:
struct SBT { int left,right,size,key; void init(int val) { left=right=0; size=1; key=val; } }tree[maxn]; int tot,root; void left_rotate(int &x) { int y=tree[x].right; tree[x].right=tree[y].left; tree[y].left=x; tree[y].size=tree[x].size; tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; x=y; } void right_rotate(int &x) { int y=tree[x].left; tree[x].left=tree[y].right; tree[y].right=x; tree[y].size=tree[x].size; tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; x=y; } void maintain(int &x,int flag) { if(!flag) { if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size) right_rotate(x); else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size) left_rotate(tree[x].left),right_rotate(x); else return; } else { if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size) left_rotate(x); else if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size) right_rotate(tree[x].right),left_rotate(x); else return; } maintain(tree[x].left,0); maintain(tree[x].right,1); maintain(x,0); maintain(x,1); } //插入值为key的节点 void insert(int &x,int key) { if(!x) { x=++tot; tree[x].init(key); } else { tree[x].size++; if(key<tree[x].key)insert(tree[x].left,key); else insert(tree[x].right,key); maintain(x,key>=tree[x].key); } } //删除值为key的节点 int del(int &x,int key) { if(!x)return 0; tree[x].size--; if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)|| (key>tree[x].key&&tree[x].right==0)) { if(tree[x].left&&tree[x].right) { int p=del(tree[x].left,key+1); tree[x].key=tree[p].key; return p; } else { int p=x; x=tree[x].left+tree[x].right; return p; } } else return del(key<tree[x].key?tree[x].left:tree[x].right,key); } //int del(int &x,int key) //{ // if(!x)return 0; // int res=0; // tree[x].size--; // if(key==tree[x].key||(key<tree[x].key&&tree[x].left==0)|| // (key>tree[x].key&&tree[x].right==0)) // { // if(tree[x].left&&tree[x].right) // { // int p=del(tree[x].left,key+1); // tree[x].key=tree[p].key; // res=p; // } // else // { // int p=x; // x=tree[x].left+tree[x].right; // res=p; // } // } // else // res=del(key<tree[x].key?tree[x].left:tree[x].right,key); // maintain(x,key<tree[x].key); // return res; //} //返回值v的前驱的值,如果没有前驱返回v本身 int Pred(int t,int v) { if(!t)return v; if(v<=tree[t].key)return Pred(tree[t].left,v); else { int tmp=Pred(tree[t].right,v); return v==tmp?tree[t].key:tmp; } } //返回值v的后继的值,如果没有后继返回v本身 int Succ(int t,int v) { if(!t)return v; if(v>=tree[t].key)return Succ(tree[t].right,v); else { int tmp=Succ(tree[t].left,v); return v==tmp?tree[t].key:tmp; } } //返回值val的前驱的编号,没有的话,返回y int get_pre(int &r,int y,int val) { if(r==0)return y; if(val>tree[r].key)//加上等号就是大于等于 return get_pre(tree[r].right,r,val); else return get_pre(tree[r].left,y,val); } //返回值val的后继的编号,没有的话,返回y int get_next(int &r,int y,int val) { if(r==0)return y; if(val<tree[r].key)return get_next(tree[r].left,r,val); else return get_next(tree[r].right,y,val); } //查找是否存在值为val的节点 int find(int r,int val) { if(r&&val!=tree[r].key) r=(val<tree[r].val?find(tree[r].left,val):find(tree[r].right,val)); return r; } //得到第k大元素的值 int get_kth(int &x,int k) { if(k<=tree[tree[x].left].size) return get_kth(tree[x].left,k); if(k>tree[tree[x].left].size+1) return get_kth(tree[x].right,k-tree[tree[x].left].size-1); return tree[x].key;//改一下就可以返回节点编号了 } //返回根为x的树最大值的编号 int get_max(int x) { while(tree[x].right)x=tree[x].right; return x; } //返回根为x的树最小值的编号 int get_min(int x) { while(tree[x].left)x=tree[x].left; return x; } //返回值val的排名 int get_rank(int &r,int val) { if(val<tree[r].val) return get_rank(tree[r].left,val); else if(val>tree[r].val) return get_rank(tree[r].right,val)+tree[tree[r].left].size+1; return tree[tree[r].left].size+1; }
相关文章推荐
- SBT 平衡二叉树模板
- P3369 【模板】普通平衡树(Treap/SBT)(pb_ds版)
- POJ3481 SBT模板题目
- 带模板的基于 SBT 的名次树
- 三大平衡树(Treap + Splay + SBT)总结+模板[转]
- 平衡二叉树模板
- P3369 【模板】普通平衡树(Treap/SBT)
- SBT 模板
- 平衡二叉树C++模板
- 【模板】bzoj-3224普通平衡树(splay&treap&SBT)
- 3224: Tyvj 1728 普通平衡树 P3369 【模板】普通平衡树(Treap/SBT)Treap
- 子树大小平衡树(SizeBalancedTree,SBT)——模板
- 一个使用sbt编译的JNI C++ 的模板
- 【模板】普通平衡树(Treap/SBT) 洛谷 3369 splay
- 洛谷 P3369 【模板】普通平衡树(Treap/SBT)
- 平衡二叉树的C++模板实现
- 三大平衡树(Treap + Splay + SBT)总结+模板
- P3369 【模板】普通平衡树(Treap/SBT)
- Size Balanced Tree(SBT) 模板
- fhq treap ------ luogu P3369 【模板】普通平衡树(Treap/SBT)