splay_tree
来源:互联网 发布:淘宝店铺主页封面 编辑:程序博客网 时间:2024/06/06 03:29
splay_tree伸展树
伸展树(Splay Tree)是二叉检索树的改进。
对伸展树的操作的平摊复杂度是O(log2n)。
伸展树的空间要求、编程难度非常低。
注意splay伸展树一定要时刻保证它的二叉检索性!
伸展树与二叉查找树一样,也具有有序性。
即伸展树中的每一个节点x都满足:该节点左子树中的每一个元素都小于x,而其右子树中的每一个元素都大于x。
伸展树可以自我调整,这就要依靠
伸展操作splay(x)了!!!
伸展操作Splay(x)是在保持伸展树有序性的前提下,通过一系列旋转操作将伸展树中的元素x调整至树的根部的操作。
在旋转的过程中,要分三种情况分别处理:
1)Zig 或 Zag
2)Zig-Zig 或 Zag-Zag
3)Zig-Zag 或 Zag-Zig
我看有些大犇的blog上直接用的rotate操作,它和splay操作本质上是一样的,不过我个人觉得splay要比rotate好想一些,也要好懂一些。
关于zig和zag的故事,我就不赘述了。
splay可以干什么?!
查找 find
插入 insert
删除 del
求最大值 get_max
求最小值 get_min
求前趋 get_pre
求后继 get_suc
求第k大 get_kth_max
求第k小get_kth_min
合并 merge
and so on......
然而.......
伸展操作是基础!
伸展操作是基础!
伸展操作是基础!
好了,废话不多说,直接上code!
#include<bits/stdc++.h>const int maxn=/**/; int ls[maxn],rs[maxn],fa[maxn],_size[maxn],val[maxn]; int n,m,x,cnt=0,delta=0;char cmd; int tot=0,root=0; ////////////左旋///////////////////////////////////////////////////////////void zig(int x){ int y=fa[x],z=fa[y]; if(ls[z]==y)ls[z]=x; else rs[z]=x; fa[x]=z; ls[y]=rs[x]; fa[rs[x]]=y; rs[x]=y; fa[y]=x; _size[x]=_size[y]; _size[y]=_size[ls[y]]+_size[rs[y]]+1; } ////////////右旋////////////////////////////////////////////////////////////void zag(int x){ int y=fa[x],z=fa[y]; if(ls[z]==y)ls[z]=x; else rs[z]=x; fa[x]=z; rs[y]=ls[x]; fa[ls[x]]=y; ls[x]=y; fa[y]=x; _size[x]=_size[y]; _size[y]=_size[ls[y]]+_size[rs[y]]+1; } ///////////伸展操作////////////////////////////////////////////////////////void splay(int x){ int y,z; while(fa[x]) { y=fa[x]; z=fa[y]; if(z) { if(ls[z]==y) { if(ls[y]==x)zig(y),zig(x); else zag(x),zig(x); } else { if(rs[y]==x)zag(y),zag(x); else zig(x),zag(x); } } else { if(ls[y]==x)zig(x); else zag(x); } } root=x; } ////////////查询操作///////////////////////////////////////////////////////int find(int key){ int p=root; while(p) { if(key==val[p])break; if(key<val[p])p=ls[p]; else p=rs[p]; } return p; } //////////插入操作////////////////////////////////////////////////////void insert(int key){ if(!tot) { val[++tot]=key; fa[tot]=0; _size[tot]=1; root=tot; return; } tot++; int p=root; while(p) { _size[p]++; if(key<val[p]) { if(ls[p])p=ls[p]; else {ls[p]=tot;break;} } else { if(rs[p])p=rs[p]; else {rs[p]=tot;break;} } } val[tot]=key; fa[tot]=p; _size[tot]=1; splay(tot);//维护平衡树 } ///////////找最大////////////////////////////////////////////////////////int get_max(int k){ int p=k; while(rs[p])p=rs[p]; return p; } ///////////找最小////////////////////////////////////////////////////////int get_min(int k){ int p=k; while(ls[p])p=ls[p]; return p; } ///////////求后继/////////////////////////////////////////////////////////int get_pre(int x){ splay(x); return get_max(ls[x]); } ///////////求前驱/////////////////////////////////////////////////////////int get_suc(int x){ splay(x); return get_min(rs[x]); } ///////////删除操作//////////////////////////////////////////////////////void del(int key){ int p=find(key); if(p) { splay(p); int left_son=ls[p],right_son=rs[p]; fa[left_son]=ls[p]=rs[p]=fa[right_son]=0; if(!left_son)root=right_son,fa[right_son]=0; else { root=left_son; left_son=get_max(left_son); splay(left_son); fa[left_son]=0; fa[right_son]=left_son; rs[left_son]=right_son; } _size[root]+=_size[rs[root]]; } } //////////求第k小/////////////////////////////////////////////////////////int get_kth_min(int k){ int p=root; while(p) { if(_size[ls[p]]+1==k)break; if(k<=_size[ls[p]])p=ls[p]; else { k-=_size[ls[p]]+1; p=rs[p]; } } splay(p); return p; } //////////求第k大///////////////////////////////////////////////////////int get_kth_max(int k){ int p=root; while(p) { if(_size[rs[p]]+1==k)break; if(k<=_size[rs[p]])p=rs[p]; else { k-=_size[rs[p]]+1; p=ls[p]; } } splay(p); return p; }///////////////////////////////////////////////////////////////// //// //// 前方高能!!! //// //// /////////////////////////////////////////////////////////////////int main(int argc,const char*argv[]){ //write your code }
阅读全文
1 0
- splay_tree
- POJ--3580[SuperMemo] Splay_Tree
- splay_tree学习+模板
- HDU--3487[Play with Chain] Splay_Tree
- 伸展树头文件C语言(splay_tree.h)
- 伸展树头文件C语言(splay_tree.h)
- 【模板】普通平衡树(洛谷3369/大视野3224)splay_tree
- AsyncTask简单的用法 点击加载图片
- leetcode 381. Insert Delete GetRandom O(1)
- 【面经笔记】红黑树的特性与其在C++ STL中的应用
- hdu 5831 Rikka with Parenthesis II
- 队列
- splay_tree
- JAVA-1009. 说反话 (20)
- CentOS 镜像文件下载中各文件的区别
- fgm实例练习笔记-3.3点击累加数字,自加1
- OpenCV3 Python语言实现 笔记4
- 51单片机的外部中断的学习(一)
- 微信小程序页面内转发 按钮 转发
- linux应用编程--pipe无名管道
- java中什么是上下文