Treap讲解

  上一篇blog提出了Treap这个算法,在这里我就要详细讲解。

  首先,我们可以从字面上理解这个算法,Treap这个单词是由Tree和Heap两个单词构成的,所以它的性质就很好理解了,明显就是同时满足Tree和Heap两个算法的性质,那么Tree是什么呢?

Heap又是什么呢?Tree是BST,而Heap是堆,如果这两个算法不懂的话可以先学习一下,因为Treap是在这两个算法的基础上产生的,BST可以看我的上一篇博客,而Heap就只能再找了,本人比较懒,没有写,见谅。

  好了言归正传,如何将BST的性质和Heap的性质结合在一起呢?似乎比较简单,我们可以在BST的基础上再开一个数组,来进行维护堆的性质,这个数组我们可以随意赋值,但是整体的数需要满足堆的性质(如左下图)。在图中的树就明显满足,val的排序方式是按照BST,而ord的排序方式是按照小根堆。这样的性质就十分靠谱,因为我每次堆ord的赋值是随机的,所以不论插入的顺序是什么,我们都可以完美的解决危机。现在问题来了,插入时找到节点了,也赋完值了,但是突然发现不满足Heap的性质了(如右下图),怎么办?

  这个时候,我们就可以引出Treap的核心部分,左旋和右旋。首先讲右旋,当当前节点的左儿子的ord小于自己的时候,我们可以进行这个操作,如下图,经过这样一个小小的变换,性质就有满足了,这个转换比较好实现,我们可以直接对节点的儿子编号进行修改还就好了。

 void rturn(int &p)
{
int tmp=lson[p];
lson[p]=rson[tmp],rson[tmp]=p;
p=tmp;
}
//lson[p]记录p号节点的左儿子的编号
//rson[p]记录p号节点的右儿子的编号

右旋

 void lturn(int &p)
{
int tmp=rson[p];
rson[p]=lson[tmp],lson[tmp]=p;
p=tmp;
}
//lson[p]记录p号节点的左儿子的编号
//rson[p]记录p号节点的右儿子的编号

左旋

  这是两个基本操作,只要写treap就需要用到。下面讲解一下基本操作:添加,单点删除。

  添加:添加操作比较简单,首先找到只满足BST性质的位置,将其添加进Treap中,如果这是一个新节点,我们可以在上面赋值ord,这是一个随机的数值,之后就可以回溯了。当每一次回溯的时候,我们需要判断一下,是否需要左旋或者右旋,即可,是不是很简单?

 void add(int &p,int number)
{
if(!p)
{
p=++idx,ct[p]=,val[p]=number;
size[p]=,ord[p]=rand();
return;
}
size[p]++;
if(val[p]==number) ct[p]++;
else if(np<number)
add(rson[p],number);
else if(np>number)
add(lson[p],number);
if(ord[rson[p]]<ord[p]) lturn(p);
if(ord[lson[p]]<ord[p]) rturn(p);
}
//ct[p]记录p号节点出现的次数
//lson[p]记录p号节点的左儿子的编号
//rson[p]记录p号节点的右儿子的编号
//val[p]记录p号节点的权值
//ord[p]记录p号节点的随机值
//size[p]记录以p号节点为根的子树的大小
//number是要插入的权值

添加

  单点删除:我们首先需要查询到当前点,如果当前点的ct>1,我们可以直接ct--,如果不是,我们需要把它旋到最下面,每一次旋转都是把自己的左儿子和右儿子中ord小的点旋上来,直到把要删除的节点旋到最下面为止,直接删去它和它父亲的连边就好了。当然,有时候会出现一种情况,就是旋到当前节点只有左儿子或者右儿子,直接把当前节点的儿子提上来就好了(如图)(注:这张图片来自http://www.cnblogs.com/huangxincheng/archive/2012/07/30/2614484.html,本人较懒,就不用画图画了)

 void del(int &p,int number)
{
if(!p) return;
if(val[p]==number)
{
if(ct[p]>)
{
ct[p]--,size[p]--;
return;
}
if(lson[p]*rson[p]==) p=lson[p]+rson[p];
else if(ord[lson[p]]<ord[rson[p]])
rturn(p),del(p,number);
else if(ord[rson[p]]<=ord[lson[p]])
lturn(p),del(p,number);
return;
}
size[p]--;
if(val[p]<number)
del(rson[p],number);
else del(lson[p],number);
}
//ct[p]记录p号节点出现的次数
//lson[p]记录p号节点的左儿子的编号
//rson[p]记录p号节点的右儿子的编号
//val[p]记录p号节点的权值
//ord[p]记录p号节点的随机值
//size[p]记录以p号节点为根的子树的大小
//number是要插入的权值

删除

大致就是这样,不会的可以评论发问题,我会解答。

Treap讲解的更多相关文章

  1. 我学到的treap

    到目前为止,平衡树应该是我学过的数据结构里面最难的一个了.(顺便贴上一个我认为treap讲解的比较好的博客https://blog.csdn.net/u014634338/article/detail ...

  2. 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)

    在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...

  3. 「模板」「讲解」Treap名次树

    Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...

  4. Treap 模板 poj1442&hdu4557

    原理可以看hihocoder上面的讲解,很清楚,不多说了. 模板抄lrj训练指南上面的. /** Treap 实现 名次树 功能: 1.找到排名为k的元素 2.值为x的元素的名次 初始化:Node* ...

  5. [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec  Mem ...

  6. [bzoj3173]最长上升子序列_非旋转Treap

    最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...

  7. BST讲解

    BST 第一步,什么是BST,所谓BST就是满足一种特定性质的二叉树,这个性质一般情况是当前节点的权值比他的左子树的所有点的权值大,比他的右子树的所有点的权值小,满足这样性质的二叉树就称为BST,下面 ...

  8. Splay讲解

    Splay讲解 Splay是平衡树的一种,是一种二叉搜索树,我们先讲解一下它的核心部分. Splay的核心部分就是splay,可能有些人会说什么鬼?这样讲解是不是太不认真了?两个字回答:不是.第一个S ...

  9. FHQ Treap小结(神级数据结构!)

    首先说一下, 这个东西可以搞一切bst,treap,splay所能搞的东西 pre 今天心血来潮, 想搞一搞平衡树, 先百度了一下平衡树,发现正宗的平衡树写法应该是在二叉查找树的基础上加什么左左左右右 ...

随机推荐

  1. JSON解析的几种方式

    在开发中,网络请求和json解析使用的频率是一样高的,因为网络请求返回来的一般都是json(当然还有xml),这里讨论的是json,网络请求的工具类前面我的博客已经写过了,这里给出网址:http:// ...

  2. JavaScript 哈希表(散列表)应用

    查找的效率与比较次数密切相关.基于比较的程序,运算效率是比较低的.比如平时可以通过indexOf查找一个数据.但这是一个基于比较的一个实现.如果是淘宝那样有上亿个商品,那么用indeOf 来查数据就会 ...

  3. Elasticsearch安装详解

    本文只介绍在windows上的安装和配置,其他安装和配置请参见官方文档 ES在windows上安装需下载zip安装包,解压后bin目录下有个 elasticsearch-service.bat 文件. ...

  4. 20162330 第十二周 蓝墨云班课 hash

    题目要求 利用除留余数法为下列关键字集合的存储设计hash函数,并画出分别用开放寻址法和拉链法解决冲突得到的空间存储状态(散列因子取0.75) 关键字集合:85,75,57,60,65,(你的8位学号 ...

  5. backpropagation

    github: https://github.com/mattm/simple-neural-network blog: https://mattmazur.com/2015/03/17/a-step ...

  6. 20162328蔡文琛week05

    学号 20162328 <程序设计与数据结构>第X周学习总结 教材学习内容总结 面向对象程序设计的核心是类的定义,它代表定义了状态和行为的对象. 变量的作用域依赖于变量声明的位置,作用域决 ...

  7. XML使用练习

    #!/usr/bin/env python # -*- coding:utf-8 -*- import requests from xml.etree import ElementTree as ET ...

  8. python之路--day11---迭代器和生成器

    迭代: 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 为什么要有迭代器: 数据类型的取值,字符串,列表,元组依靠索引可以取值,但是字典,集合,文件这些数据类型无法 ...

  9. ESP8266 wifi 模块配置,Wechat+APP控制实现

    首先刷入安信可的AiCloud 2.0 SDK文件,AiCloud 2.0具体信息参见AiCloud 1.0 和AiCloud 2.0对比 APP见如下二维码下载. 1.安信可AiCloud 2.0 ...

  10. Python内置函数(30)——super

    英文文档: super([type[, object-or-type]]) Return a proxy object that delegates method calls to a parent ...