Treap(树堆)
treap是排序二叉树的一种改进,因为排序二叉树有可能会造成链状结构的时候复杂度变成O(n^2)所以通过随机一个优先级的方法来维持每次让优先级最大的作为树根,然后形成一个满足:
A. 节点中的key满足排序二叉树(二叉查找树)
B. 节点中的“优先级”满足大顶堆。
可以证明通过这种方法维持的插入、删除、查找的期望时间复杂度为O(logn)

一、节点的定义:左右孩子用指针数组的形式储存
struct Node{
Node*ch[];//左右子树
int r;//优先值
int v;//值
int cmp(int x) const{
if(x==v)return -;
return x<v?:;//0在ch[0]中正好是左孩子,对应向左搜索和操作,1在ch[1]中是右孩子,对应向右搜索和操作
}
};
二、旋转:和大顶堆的调整方法类似,左旋和右旋,用于对优先级的堆排序,这里不会影响二叉排序树的性质,介绍一种位运算可以巧妙的进行左旋和右旋的选择——异或,相同为0,不同为1,那么x^1就是对x取反的操作。
现在以下图为例
o 表示的指向根节点的指针
有旋转的代码如下:
//左旋代码
k = o->ch[];
o->ch[] = k->ch[];
k->ch[] = o;
o = k;
//右旋代码
k = o->ch[];
o->ch[] = k->ch[];
k->ch[] = o;
o = k;
//两种代码可以写成一种,利用异或
void rotate(Node* &o,int d){//d = 0 左旋,d = 1 右旋
Node *k = o->ch[d^];
o->ch[d^] = k->ch[d];
k->ch[d] = o;
o = k;
}
三、插入: 在插入的时候除了要在满足排序二叉树的插入要求,即递归的操作之外,还要满足堆的相应操作,所以,要通过旋转来实现,下面是代码:
srand(time(NULL));
void insert(Node *&o, int x){
if(o==NULL){
o = new Node();
o->ch[] = o->ch[] = NULL;
o->v = x;
o->r = rand();
}
else {
int d = o->cmp(x);//如果要插入的值x比当前根节点的值小则d==0,向左子树寻找,这里可以看出定义指针数组的好处
insert(o->ch[d],x);
if(o->ch[d]->r > o->r) rotate(o,d^);//左孩子权值大右旋,右孩子权值大左旋
}
}
四、删除:如果待删除结点为叶子结点或只有一棵子树,则用其子树(可能为空)替代它即可。如果有两棵子树,则将孩子中优先级高的旋转到根,然后在另一棵子树中递归删除目标点。
代码如下:
void remove(Node *&o,int x){
int d = o->cmp(x);
if(d==-){//找到了
if(o->ch[] == NULL) o = o->ch[];
else if(o->ch[] == NULL) o = o->ch[];
else {
int d2 = ((o->ch[]->r)>(o->ch[]->r)?:);//删除节点的左孩子权值大右旋,右孩子权值大左旋
rotate(o,d2);
remove(o->ch[d2],x);
}
}
else remove(o->ch[d],x);
}
五、查找:在插入和查找前进行查找,防止特殊情况,代码如下
int find(Node*o, int x){
while(o!=NULL){
int d = o->cmp(x);
if(d==-) return ;//找到了
else o = o->ch[d];
}
return ;//不存在
}
六、应用,这个数据结构可以用来解决二叉排序树的超时问题
X]C71D1GEUN`5)H]T.png)
Treap(树堆)的更多相关文章
- BZOJ3224/LOJ104 普通平衡树 treap(树堆)
您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x2. 删除x(若有多个相同的数,因只删除一个)3. 查询x的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. ...
- 可旋转Treap(树堆)总结
树堆,在数据结构中也称Treap,是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树.其基本操作的期望时间复杂度为O(logn).相对于其他的平衡二叉搜索树,Trea ...
- treap(树堆)
一棵treap是一棵修改了结点顺序的二叉查找树,如图,显示一个例子,通常树内的每个结点x都有一个关键字值key[x],另外,还要为结点分配priority[x],它是一个独立选取的随机数. 假设所有的 ...
- 查找——图文翔解Treap(树堆)
之前我们讲到二叉搜索树,从二叉搜索树到2-3树到红黑树到B-树. 二叉搜索树的主要问题就是其结构与数据相关,树的深度可能会非常大,Treap树就是一种解决二叉搜索树可能深度过大的还有一种数据结构. T ...
- 树堆(Treap)学习笔记 2020.8.12
如果一棵二叉排序树的节点插入的顺序是随机的,那么这样建立的二叉排序树在大多数情况下是平衡的,可以证明,其高度期望值为 \(O( \log_2 n )\).即使存在一些极端情况,但是这种情况发生的概率很 ...
- Treap树的基础知识
原文 其它较好的的介绍:堆排序 AVL树 树堆,在数据结构中也称Treap(事实上在国内OI界常称为Traep,与之同理的还有"Tarjan神犇发明的"Spaly),是指有一个随 ...
- Treap树
Treap树算是一种简单的优化策略,这名字大家也能猜到,树和堆的合体,其实原理比较简单,在树中维护一个"优先级“,”优先级“ 采用随机数的方法,但是”优先级“必须满足根堆的性质,当然是“大根 ...
- 6天通吃树结构—— 第三天 Treap树
原文:6天通吃树结构-- 第三天 Treap树 我们知道,二叉查找树相对来说比较容易形成最坏的链表情况,所以前辈们想尽了各种优化策略,包括AVL,红黑,以及今天 要讲的Treap树. Treap树算是 ...
- Treap树 笔记
预备知识:二叉查找树.堆(heap).平衡二叉树(AVL)的基本操作(左旋右旋) 定义: Treap.平衡二叉树.Tree+Heap.树堆. 每个结点两个键值(key.priority). 性质1. ...
- 真·浅谈treap树
treap树是一种平衡树,它有平衡树的性质,满足堆的性质,是二叉搜索树,但是我们需要维护他 为什么满足堆的性质?因为每个节点还有一个随机权值,按照随机权值维持这个堆(树),可以用O(logn)的复杂度 ...
随机推荐
- JAVA多线程统计日志计数时的线程安全及效率问题
最近工作上遇到一个需求:需要根据nginx日志去统计每个域名的qps(Query Per Second,每秒查询率)数据. 解决了日志读取等问题之后,为了写一个尽可能高效的统计模块,我决定用多线程去计 ...
- 通过 JS 判断页面是否有滚动条的简单方法
前言 最近在写插件的过程中,需要使用 JS 判断是否有滚动条,搜了一下,大致方法都差不多,但都有些啰嗦,代码不够简洁.最终通过参考不同方法,写了一个比较简单的方法.在判断滚动条的同时也需要计算滚动条的 ...
- SDP(0):Streaming-Data-Processor - Data Processing with Akka-Stream
再有两天就进入2018了,想想还是要准备一下明年的工作方向.回想当初开始学习函数式编程时的主要目的是想设计一套标准API給那些习惯了OOP方式开发商业应用软件的程序员们,使他们能用一种接近传统数据库软 ...
- Pytorch windows10安装教程
强烈建议安装anaconda之后再来安装这个pytorch,具体怎么安装百度搜索就知道了. 温馨提示,在安装anaconda的时候记得将"添加到环境变量"(安装的时候是英文的)这一 ...
- Thymeleaf引擎支持Multi Prefix
最近团队的一个项目在重构,希望引入Thymeleaf减少页面端的代码复杂性.在重构过程中,发现html文件需要保存在多个不同的目录中,但Thymeleaf缺省的实现不支持这种方式. 1 ...
- Linux第三节
三期第三讲1.ls --help:查看帮助(man 命令) :ls -l: 长格式形式: ls -i: 文件的inode节点: ls -t: 按修改时间排序: ls -a :显示隐藏文件: 2.文件管 ...
- 限制ssh远程登陆
超过十次,就添加到hosts.deny里面去 #!/bin/bash date=`date +%Y%m%d` file="/var/log/secure" max=10 if [[ ...
- Android开发之漫漫长途 IX——彻底掌握Binder
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Parallels Desktop 12
我微新solq123987654 备注:PD 科普:PD12有什么用,PD是让mac系统可以运行wind系统的软件,如果你不习惯mac os 或工作需要那PD绝对是个好软件正版要七八百授权,只要十五就 ...
- CDN 边缘规则,三秒部署、支持定制、即时生效,多种规则覆盖常用业务场景
2017年的最后一周,又拍云进行了一次重要升级,将自定义 Rewrite 升级为"边缘规则".互联网应用场景的日益多样化,简单.方便.快速的根据不同应用场景实现不同的功能变得越来越 ...