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 ;//不存在
}

六、应用,这个数据结构可以用来解决二叉排序树的超时问题

Treap(树堆)的更多相关文章

  1. BZOJ3224/LOJ104 普通平衡树 treap(树堆)

    您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x2. 删除x(若有多个相同的数,因只删除一个)3. 查询x的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. ...

  2. 可旋转Treap(树堆)总结

    树堆,在数据结构中也称Treap,是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树.其基本操作的期望时间复杂度为O(logn).相对于其他的平衡二叉搜索树,Trea ...

  3. treap(树堆)

    一棵treap是一棵修改了结点顺序的二叉查找树,如图,显示一个例子,通常树内的每个结点x都有一个关键字值key[x],另外,还要为结点分配priority[x],它是一个独立选取的随机数. 假设所有的 ...

  4. 查找——图文翔解Treap(树堆)

    之前我们讲到二叉搜索树,从二叉搜索树到2-3树到红黑树到B-树. 二叉搜索树的主要问题就是其结构与数据相关,树的深度可能会非常大,Treap树就是一种解决二叉搜索树可能深度过大的还有一种数据结构. T ...

  5. 树堆(Treap)学习笔记 2020.8.12

    如果一棵二叉排序树的节点插入的顺序是随机的,那么这样建立的二叉排序树在大多数情况下是平衡的,可以证明,其高度期望值为 \(O( \log_2 n )\).即使存在一些极端情况,但是这种情况发生的概率很 ...

  6. Treap树的基础知识

    原文 其它较好的的介绍:堆排序  AVL树 树堆,在数据结构中也称Treap(事实上在国内OI界常称为Traep,与之同理的还有"Tarjan神犇发明的"Spaly),是指有一个随 ...

  7. Treap树

    Treap树算是一种简单的优化策略,这名字大家也能猜到,树和堆的合体,其实原理比较简单,在树中维护一个"优先级“,”优先级“ 采用随机数的方法,但是”优先级“必须满足根堆的性质,当然是“大根 ...

  8. 6天通吃树结构—— 第三天 Treap树

    原文:6天通吃树结构-- 第三天 Treap树 我们知道,二叉查找树相对来说比较容易形成最坏的链表情况,所以前辈们想尽了各种优化策略,包括AVL,红黑,以及今天 要讲的Treap树. Treap树算是 ...

  9. Treap树 笔记

    预备知识:二叉查找树.堆(heap).平衡二叉树(AVL)的基本操作(左旋右旋) 定义: Treap.平衡二叉树.Tree+Heap.树堆. 每个结点两个键值(key.priority). 性质1. ...

  10. 真·浅谈treap树

    treap树是一种平衡树,它有平衡树的性质,满足堆的性质,是二叉搜索树,但是我们需要维护他 为什么满足堆的性质?因为每个节点还有一个随机权值,按照随机权值维持这个堆(树),可以用O(logn)的复杂度 ...

随机推荐

  1. iis 10 ftp 被动模式配置

    第一步: 进入 Server Level 的FTP Firewall Support 第二步: 在 Data Channel Port Range 下配置 Passive mode 的端口号范围,注意 ...

  2. JaveScript流程控制(JS知识点归纳四)

    01 流程控制 顺序结构: 程序的默认执行方式 条件判断语句:也称之为分支结构,选择结构:如果程序要执行的代码出现了多种情况需要使用 循环结构:当代码需要多次重复执行多次时,使用 02 条件判断语句 ...

  3. JFinal极速开发框架使用笔记

    记录第一次使用JFinal,从简单的框架搭建到增删改查,从自带的方法到正常框架习惯的使用方式. JFinal官网:http://www.jfinal.com/ JFinal 是基于 Java 语言的极 ...

  4. Nginx (二) Nginx的反向代理负载均衡以及日志切割

    Nginx是一个高并发,高性能的服务器,可以进行反向代理以及网站的负载均衡.这些功能的运用都在配置文件中,也就是Nginx安装目录下的conf/nginx.conf. nginx.conf 1. 先来 ...

  5. iOS使用带字体图标的UIButton(支持各种方向)

    简书地址:http://www.jianshu.com/p/1c288440754d demo地址:https://github.com/Brances/ZMProject

  6. eclipse 更换 JDK 版本后报错

    在实际开发过程中,可能由于项目的需要,我们需要更换 JDK 的版本.但是更换后会报错,如下: Java compiler level does not match the version of the ...

  7. centos 命令

    1.查看占用端口的进程 netstat -lnp|grep 3000(3000为端口号) Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statis ...

  8. spring项目读取配置文件

    Spring项目在运用中读取配置文件有两种方式: 通过项目的配置文件读取 在spring-context.xml里面加入以下代码 在运用到的类里面加入 @Value("#{configPro ...

  9. Linux系统编程:简单文件IO操作

    使用Linux的文件API,经常看见一个东西,叫做文件描述符. 什么是文件描述符? (1)文件描述符其实实质是一个数字,这个数字在一个进程中表示一个特定的含义,当我们open打开一个文件时,操作系统在 ...

  10. Java实现贪吃蛇游戏【代码】

    花了两个下午写了一个贪吃蛇小游戏,本人想写这游戏很长时间了.作为以前诺基亚手机上的经典游戏,贪吃蛇和俄罗斯方块一样,都曾经在我们的童年给我们带来了很多乐趣.世间万物斗转星移,诺基亚曾经作为手机业的龙头 ...