之前我们讲到二叉搜索树,从二叉搜索树到2-3树到红黑树到B-树。

二叉搜索树的主要问题就是其结构与数据相关,树的深度可能会非常大,Treap树就是一种解决二叉搜索树可能深度过大的还有一种数据结构。

Treap

Treap=Tree+Heap。

Treap本身是一棵二叉搜索树,它的左子树和右子树也各自是一个Treap。和一般的二叉搜索树不同的是。Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉搜索树的同一时候,还满足堆的性质。这些优先级是是在结点插入时,随机赋予的。Treap依据这些优先级满足堆的性质。这种话,Treap是有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树

其基本操作的期望时间复杂度为O(logn)。相对于其它的平衡二叉搜索树,Treap的特点是实现简单。且能基本实现随机平衡的结构。

Treap维护堆性质的方法仅仅用到了旋转。仅仅须要两种旋转。编程复杂度比Splay要小一些。

插入

给节点随机分配一个优先级,先和二叉搜索树的插入一样,先把要插入的点插入到一个叶子上,然后跟维护堆一样。假设当前节点的优先级比根大就旋转,假设当前节点是根的左儿子就右旋,假设当前节点是根的右儿子就左旋。

以下图解旋转操作:


因为旋转是O(1)的。最多进行h次(h是树的高度)。插入的复杂度是O(h)的。在期望情况下h=O(logn)。所以它的期望复杂度是O(logn)。 

 

以下我们以一个实例来图解Treap的插入过程。看完之后你一定对Treap的插入了然于胸。




删除

删除一个节点有两种方式。能够像删除二叉树节点那样删除一个节点。也能够像删除堆中节点那样删除。

1、用二叉搜索树的方式删除

先在二叉查找树中找到要删除的节点的位置,然后依据节点分下面情况:

情况一:

该节点是叶节点(没有非空子节 点的节点),直接把节点删除就可以。



情况二:

该节点是链节点(仅仅有一个非空子节点的节点),为了删除这个节点而不影响它的子树,须要把它的子节点取代它的位置,然后把它删除。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuZ195dWxlaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="400" height="220" alt="">


情况三:

该节点有两个非空子节点。因为情况比較复杂,一般的策略是用它右子树的最小值来取代它,然后把它删除。如图所看到的,删除节点2时,在它的右子树中找到最小的节点3, 该节点一定为待删除节点的后继。删除节点3(它可能是叶节点或者链节点),然后把节点2的值改为3。

(当然,我们也能够使用结点的左子树的最大值来替代它,为了不使Treap向一边偏沉,我们能够随机地选取是用后继还是前驱取代它, 并保证两种选择的概率均等。)

关于查找最小值:

基本方法就是从子树的根节点開始, 假设左子节点不为空,那么就訪问左子节点,直到左子节点为空,当前节点就是该子树的最 小值节点。删除它仅仅需用它的右子节点取代它本身。

2、用堆的方式删除

由于Treap满足堆性质,所以仅仅须要把要删除的节点旋转到叶节点上。然后直接删除就能够了。

详细的方法:

假设该节点的左子节点的优先级小于右子节点的优先级。右旋该节点,使该节点降为右子树的根节点,然后訪问右子树的根节点,继续操作。

反之,左旋该节点,使该节点降为左子树的根节点,然后訪问左子树的根节点。继续操作,直到变成能够直接删除的节点。

(即:让小优先级的结点旋到上面,满足堆的性质)

删除最多进行O(h)次旋转,期望复杂度是O(logn)。

查找

和一般的二叉搜索树一样。可是因为Treap的随机化结构,Treap中查找的期望复杂度是O(logn)。

对照

与 Splay树 相比:

Splay 和 BST 一样,不须要维护不论什么附加域,比 Treap 在空间上有节约。但 Splay 在查找时也会调整结构,这使得 Splay 灵活性稍有欠缺。Splay 的查找插入删除等基本操作的时间复杂度为均摊O(logN)而非期望。能够有益构造出使 Splay 变得非常慢的数据。



与AVL 红黑树相比:

AVL 和红黑树在调整的过程中,旋转都是均摊 O(1)的,而 Treap 要 O(logN)。

与 Treap 的随机优先级不同,它们维护的附加域要动态的调整,而 Treap 的随机修正值一经生成不再改变,这一点使得灵活性不如 Treap。

AVL 和红黑树都是时间效率非常高的经典算法,在很多专业的应用领域(如 STL)有着十分重要的地位。然而AVL和红黑树的编程实现的难度要比Treap大得多。

维护子树的大小

Treap 是一种排序的数据结构,假设我们想查找第k小的元素或者询问某个元素在Treap中从小到大的排名时,我们就必须知道每一个子树中节点的个数。

因为插入、删除、旋转等操作,会使每一个子树的大小改变,所 以我们必须对子树的大小进行动态的维护。



对于旋转,我们要在旋转后对子节点和根节点分别又一次计算其子树的大小。 

对于插入,在寻找插入的位置时,每经过一个节点,都要先使以它为根的子树的大小添加 1,再递归进入子树查找。 

对于删除,在寻找待删除节点,递归返回时要把全部的经过的节点的子树的大小降低 1。

要注意的是,删除之前一定要保证待删除节点存在于 Treap 中。

(维护了子树的大小,我们就能够求“排名第k的元素”这种问题了。

快排也能求“第k大”问题,可是快排适合静态的数据,对于常常变动的数据。我们用树结构来维护更灵活。)

(我们还能够求“某个元素的排名”。我们的基本思想是查找目标元素在 Treap 中的位置,且在查找路径中统计出小于目标元素的节点的总个数,目标元素的排名就是总个数+1。即:在查找的路径中统计小于目标元素的个数,当找到目标元素后加上其左子树的个数就可以。)

举个栗子

Treap 是一种高效的动态的数据容器,据此我们能够用它处理一些数据的动态统计问题。



一、一个应用实例

[问题描写叙述] 有一个游戏排名系统,通常要应付三种请求:上传一条新的得分记录、查询某个玩家的当前 排名以及返回某个区段内的排名记录。

当某个玩家上传自己最新的得分记录时,他原有的得 分记录会被删除。

为了减轻server负担,在返回某个区段内的排名记录时,最多返回 10 条 记录。

[求]

(1)更新玩家的得分记录

(2)查询玩家排名(假设两个玩家的得分同样, 则先得到该得分的玩家排在前面。



(3)查询第 Index 名開始的最多 10 名玩家名字



[解]

由于作为字符串的姓名是不便于处理的,我们给每一个玩家都制定一个ID,首先要建立一个由姓名到玩家ID的映射数据结构。

为了查找高速,能够用Trie树。之后我们建立一个双keyword的Treap,keyword1为得分从小到大,keyword2为时间戳从大到小,这样的排列方式的逆序,恰好是我们要的顺序(也能够直接就是逆序)。

对于问题(1),先查询玩家是否已经存在,假设已经存在,在Treap中更新相应已经存在的记录。

对于问题(2),就是主要的求排名操作。

对于问题(3)。就是分别查找第(总记录数 + 1 – k)小的记录。



二、双端优先队列的实现

优先队列(Priority Queue)是一种按优先级维护进出顺序的数据容器结构,能够选择维护实现取出最小值或最大值。我们通经常使用堆实现优先队列,通常取出最值的时间复杂度为 O(logN)。

用最小堆能够实现最小优先队列,用最大堆能够实现最大优先队列。可是假设我们要求一种 “双端优先队列”,即要求同一时候支持插入、取出最大值、取出最小值的操作,用一个单纯的堆就不能高效地实现了。

(能够用两个堆来实现,两堆中的元素都互指,但维护两个堆比較复杂。)



我们能够方便地使用Treap实现双端优先队列,仅仅需建立一个 Treap,分别写出取最大值和最小值的功能代码就能够了, 无需做不论什么改动。

因为Treap平衡性不如堆完美,但期望时间仍是 O(logN)。更重要的是在 实现的复杂程度上大大下降,并且便于其它操作的推广。所以,用 Treap 实现优先队列不失为一种便捷而又灵活的方法。

其他:

平衡树并不适合作为全部数据类型的数据的有序存储容器,由于可能有些类型的两个元素直接相互比較大小是十分 耗时的,这个常数时间的消耗是无法忍受的。比如字符串,作为检索字符串的容器,我们更推荐Trie树,而不是平衡树。平衡树仅适合做元素间相互比較时间非常少的类型的有序存储容器。

关于查找最小值:

基本方法就是从子树的根节点開始, 假设左子节点不为空,那么就訪问左子节点,直到左子节点为空,当前节点就是该子树的最 小值节点。删除它仅仅需用它的右子节点取代它本身。

【參考】

中文维基百科http://zh.wikipedia.org/wiki/%E6%A0%91%E5%A0%86

《随机平衡二叉查找树Treap的分析与应用》 清华大学计算机系 郭家宝


---------------------------------------------
感谢訪问,随手点赞,点滴慈善^_^
---------------------------------------------


查找——图文翔解Treap(树堆)的更多相关文章

  1. 查找——图文翔解HashTree(哈希树)

    引 在各种数据结构(线性表.树等)中,记录在结构中的相对位置是随机的.因此在机构中查找记录的时须要进行一系列和keyword的比較.这一类的查找方法建立在"比較"的基础上.查找的效 ...

  2. 查找——图文翔解SkipList(跳跃表)

    跳跃表 跳跃列表(也称跳表)是一种随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作须要O(logn)平均时间). 基本上.跳跃列表是对有序的链表添加上附加的前进链接,添加是以随 ...

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

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

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

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

  5. treap(树堆)

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

  6. B树和B+树的插入、删除图文详解(good)

    B树和B+树的插入.删除图文详解 1. B树 1. B树的定义 B树也称B-树,它是一颗多路平衡查找树.我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数 ...

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

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

  8. 数据结构图文解析之:树的简介及二叉排序树C++模板实现.

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  9. Treap树理解

    title: Treap树理解 comments: true date: 2016-10-06 07:57:37 categories: 算法 tags: Treap树 树 Treap树理解 简介 随 ...

随机推荐

  1. LGA(land grid array)

    产品应用 1.射频功放 2.加速度传感器 3.地磁传感器 可靠性 Reliability 高压蒸煮 PCT 121℃,100%RH,2atm,96hrs 高低温循环 TCT -55℃(15min)~1 ...

  2. 用U盘装win7/XP系统的操作

    现在上网本越来越流行了,但是上网本是没有光驱的,那如何给上网本装系统就成了一个难题,其实不仅仅不带光驱的笔记本用户愁怎么装系统,那些没有光驱的台式机用户也愁.为了给这类用户提供方便,笔者今天以上网本装 ...

  3. 转自:Python函数式编程指南(二):函数

    2. 从函数开始 2.1. 定义一个函数 如下定义了一个求和函数: 1 2 def add(x, y):     return x + y 关于参数和返回值的语法细节可以参考其他文档,这里就略过了. ...

  4. HDU 5700 区间交(线段树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5700 [题目大意] 给出一个长度为n的数列和m个区间,现在求k个区间,使得他们的区间交内的数列项和 ...

  5. EF 6 调用存储过程时返回多结果集和OUTPUT参数问题

    原文地址:http://q.cnblogs.com/q/56836/ 各位大侠,提问一个关于EF6调用存储过程时返回多结果集和OUTPUT参数问题 目前已经可以调用存储过程并且可以返回多个结果集. 但 ...

  6. why constrained regression and Regularized regression equivalent

    problem 1: $\min_{\beta} ~f_\alpha(\beta):=\frac{1}{2}\Vert y-X\beta\Vert^2 +\alpha\Vert \beta\Vert$ ...

  7. asp-net-web-api 自定义URl插件

    http://attributerouting.net/#asp-net-web-api https://github.com/johnpapa/CodeCamper/blob/master/Code ...

  8. .net通用权限框架B/S (五)--WEB(3)组织机构

    .net通用权限框架B/S 首先我们看导航菜单中,对组织机构的设置 我们设置了组织机构名称,链接(对应的mvc控制器名/orga),图标是个小钥匙,菜单的操作权限设置的是"添加,编辑,删除& ...

  9. 2014.12.06 ASP.NET 三级联动,添加员工,修改员工

    (一)三级联动 要实现的效果: 代码: MyDBDataContext context = new MyDBDataContext(); protected void Page_Load(object ...

  10. SqlServer mssql 按月统计所有部门

    以订单统计为例,前端展示柱状图(Jquery统计): 表及主要字段描述如下:表名:Orders1.日期CreateTime2.金额Amount3.用户UserID 情况一:根据部门统计某一年每月销量( ...