平衡树之Treap—强大的数据结构
来源:互联网 发布:淘宝怎么看价格走势 编辑:程序博客网 时间:2024/06/07 14:50
Treap介绍
正题
构建
构建一棵
第一种是较为简单,将数按顺序加入,并给加入的元素附上一个随机优先级,在对元素进行插入操作即可。时间复杂度
第二种就是直接维护一个栈。考虑到优先级会随着深度的增加而减小,因此可以维护一个栈来完成
如果实在不会第二种用第一种也无妨,毕竟要维护一棵
插入
首先先按照二叉搜索树的插入一样将元素插入到一个叶节点上,然后就从下往上维护堆的性质,利用旋转操作,如果儿子节点的优先级比父亲优的话就把儿子节点旋转至他父亲的位置。因为期望树高是
附上代码。
Code:
//tree[x].size是指以x为根的子树大小//tree[x].v是指以x节点的实际数值//tree[x].l和tree[x].r分别是指x的左儿子和右儿子//tree[x].rnd是指x的随机优先级//leftturn是左旋操作,rightturn是右旋操作//接下来的都一样,就不加注释了void insert(int &k,int x)//此Treap为小根堆{ if(!k) { k=++size; tree[k].size=1;tree[k].v=x;tree[k].rnd=rand(); return; } tree[k].size++; else if(x>tree[k].v) { insert(tree[k].r,x); if(tree[tree[k].r].rnd<tree[k].rnd)leftturn(k);//维护堆性质 } else { insert(tree[k].l,x); if(tree[tree[k].l].rnd<tree[k].rnd)rightturn(k); } }
删除
先找到要删除的那个节点,然后把该节点优先级较大的儿子旋转到自己的位置,直到该节点选转到了叶节点的位置,便可以直接删除了。期望时间复杂度
附上代码。
Code:
void del(int &k,int x){ if(!k)return; if(tree[k].v==x) { if(tree[k].l*tree[k].r==0)k=tree[k].l^tree[k].r;//有一个儿子为空 else if(tree[tree[k].l].rnd<tree[tree[k].r].rnd) rightturn(k),del(k,x); else leftturn(k),del(k,x); } else if(x>tree[k].v) tree[k].size--,del(tree[k].r,x); else tree[k].size--,del(tree[k].l,x);}
查找
查找和一般的二叉排序树一样,但是由于
区别
其次就是
再然后,
总而言之,
可持久化Treap
如果你认真研究
可持久化
分离(split)
分离操作会将一棵
具体实现如下,每次要从以
看看代码理解会更好。
Code:
//change(o)是指重新计算节点o的信息(更新节点o的信息)//down(o)是指将o的标记下传至儿子节点//下面merge也是一样#define fi first#define se secondtypedef pair<int,int> P;P split(int o,int k){ if(!k)return P(0,o); down(o); if(size[tree[o].l]>=k){ P ls=split(tree[o].l,k); tree[o].l=ls.se; change(o); return P(ls.fi,o); } P ls=split(tree[o].r,k-tree[tree[o].l].size-1); tree[o].r=ls.fi; change(o); return P(o,ls.se);}
合并(merge)
函数
期望复杂度为树高,即
还是看看代码好,一开始我都是看代码看会的,很好理解,合并的代码如下
Code:
int merge(int a,int b){ if((!a)||(!b))return a^b; down(a); down(b); if(tree[a].rnd>tree[b].rnd){ tree[a].r=merge(tree[a].r,b); change(a); return a; } tree[b].l=merge(a,tree[b].l); change(b); return b;}
可持久化Treap的其他操作
注释:接下来的
插入
对于插入操作,例如我要在
还是那句话,看看标程帮助理解。
Code:
#define fi first#define se secondtypedef pair<int,int> P;int insert(int root,int x,int k){ P ls=split(root,k); tree[++size]=x; tree[size].rnd=rand()%123456789; tree[size].size=1; root=merge(ls.fi,size); root=merge(root,ls.se); return root;}
删除
对于删除操作,例如我要删除
看看代码。
Code:
#define fi first#define se secondtypedef pair<int,int> P;int del(int root,int k){ P ls=split(root,k); P s=split(ls.fi,k-1); root=merge(s.fi,ls.se); return root;}
区间修改和询问
有了
利用
询问也差不多是这样吧,都是分成三棵子树。
这个就没有必要写什么代码了,自己理解就好。
可持久化操作
仔细想一下,对于每次操作,都是由多个的
总结
相对于普通的
可持久化
除此之外,可持久化
如果有什么错误或可以改进的地方,还请各位大佬指出,谢谢。
就这么多了,希望能够帮助到大家。
- 平衡树之Treap—强大的数据结构
- 数据结构之平衡树(Treap)
- 数据结构 平衡树treap
- 【数据结构】Treap——方便的平衡树
- 平衡树之treap
- 平衡树之Treap
- 平衡树之treap
- 数据结构 平衡树 Treap讲解
- 数据结构之Treap树
- 平衡树——Treap
- Treap--简单的平衡二叉搜索树
- 平衡的美 treap
- 二叉排序树,平衡二叉树,Treap平衡树的实现-转帖
- 偷懒专用平衡树——Treap
- ACM:平衡树(1)——Treap
- TREAP平衡树代码
- Treap平衡树
- Treap平衡树
- Linux中切换用户变成-bash4.1-$的解决方法
- Firefly-RK3288 Linux硬件加速,可安装Kodi
- 多线程 锁对象改变
- 视频文件MD5值获取及校验
- 锤子招募众测用户@所有人
- 平衡树之Treap—强大的数据结构
- 一劳永逸的flex布局
- ionic2中强制使安卓用ios样式的方法
- mybatis学习总结思维导图:
- Python中使用多个分隔符分隔字符串re.split
- 在SpringBoot中获取某个注解标记的`BeanName`
- idea在搭建ssm框架时mybatis整合问题
- QGC中QGCTool
- HTTP中GET与POST的区别