Treap-平衡树学习笔记
平衡树-Treap学习笔记
最近刚学了Treap
发现这种数据结构真的是——妙啊妙啊~~
咳咳。。。。
所以发一发博客,也是为了加深蒟蒻自己的理解
顺便帮助一下各位小伙伴们
切入正题
Treap的结构体
首先,Treap有两个定义
对于权值而言,它是二叉查找树
对于优先级而言,它是堆
由此,我们将Treap保存于结构体内
struct node
{
node* ch[2];//左右孩子指针,0为左孩子,1,为右孩子
int v,r;//v为该节点权值;r为优先级
node(int v):v(v){ r=rand(); ch[0]=ch[1]=NULL;}
//构造函数,用于初始化
int cmp(int x) const{ if(x==v) return -1; return x<v ?0:1; }
//这里的这个成员函数将在下面解释
};
node* rt=NULL;//这个是初始的根
旋转
既然平衡树
最重要的当然是旋转啦
先上一张baidu的图
结合图理解才透彻嘛
在这张图里面
我们要将中间那个圆节点旋转到根的位置
调用函数时的参数是图中最上面那个节点
(我这样说会不会有点不明白)
//d=0代表左旋;d=1代表右旋
void rotate(node* &p,int d)//结点记得加引用
{
node* k=p->ch[d^1];
p->ch[d^1]=k->ch[d];
k->ch[d]=p;
p=k;
}
其实看着图自己模拟一下就懂了
应该不用注释了吧
插入
既然Treap是二叉查找树
那么插入自然按照二叉查找树节点的性质啦
即每个结点的左孩子权值一定小于该节点,而右孩子反之
只要按照二叉查找树的插入方式递归寻找带插入位置就好
然而
Treap还是个堆啊
所以插入后还要判断优先级
之前我们初始化优先级r为随机rand()
从而保证了整个程序平均的运行效率
void ins(node* &p,int x)//x为带插入权值,结点记得加引用
{
if(p==NULL){ p=new node(x); return; }
//如果结点为NULL ,则找到了带插入结点,进行初始化
int d=p->cmp(x);
//这里运用了结构体中的cmp函数,用以确定x该插入左孩子还是右孩子
//若x<该结点权值,cmp返回0,插入左孩子;反之亦然
ins(p->ch[d],x);
//递归插入
if( p->ch[d]->r < p->r ) rotate(p,d^1);
//*划重点*;插入后判断优先级以保证堆的性质
}
删除
寻找待删除结点依照二叉查找树的性质
这里主要讨论找到待删除结点后的操作
void del(node* &p,int x)//结点记得加引用
{
if(p==NULL) return;//找到空结点就返回
if(x==p->v)//找到待删除结点
{
if(p->ch[0]==NULL)
{node *k=p; p=p->ch[1]; delete(k); return;}
else if(p->ch[1]==NULL)
{node *k=p; p=p->ch[0]; delete(k); return;}
//如果这个结点只有一棵子树,就以该子树代替该节点
else//如果两棵子树都不为空
{
//先把优先级较高的子树旋转到根
//然后递归再另一颗子树中删除p
int dd=p->ch[0]->r < p->ch[1]->r ?1 :0;
rotate(p,dd); del(p->ch[dd],x);
return;
}
}
//递归寻找待删除结点
int d=p->cmp(x);
del(p->ch[d],x);
}
Treap的基本操作就这些啦
蒟蒻的OI路还是漫漫无期
Treap-平衡树学习笔记的更多相关文章
- 平衡树学习笔记(2)-------Treap
Treap 上一篇:平衡树学习笔记(1)-------简介 Treap是一个玄学的平衡树 为什么说它玄学呢? 还记得上一节说过每个平衡树都有自己的平衡方式吗? 没错,它平衡的方式是......rand ...
- 平衡树学习笔记(6)-------RBT
RBT 上一篇:平衡树学习笔记(5)-------SBT RBT是...是一棵恐怖的树 有多恐怖? 平衡树中最快的♂ 不到200ms的优势,连权值线段树都无法匹敌 但是,通过大量百度,发现RBT的代码 ...
- 平衡树学习笔记(5)-------SBT
SBT 上一篇:平衡树学习笔记(4)-------替罪羊树 所谓SBT,就是Size Balanced Tree 它的速度很快,完全碾爆Treap,Splay等平衡树,而且代码简洁易懂 尤其是插入节点 ...
- 平衡树学习笔记(3)-------Splay
Splay 上一篇:平衡树学习笔记(2)-------Treap Splay是一个实用而且灵活性很强的平衡树 效率上也比较客观,但是一定要一次性写对 debug可能不是那么容易 Splay作为平衡树, ...
- BST,Splay平衡树学习笔记
BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...
- [普通平衡树treap]【学习笔记】
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9046 Solved: 3840[Submit][Sta ...
- 普通平衡树学习笔记之Splay算法
前言 今天不容易有一天的自由学习时间,当然要用来"学习".在此记录一下今天学到的最基础的平衡树. 定义 平衡树是二叉搜索树和堆合并构成的数据结构,它是一 棵空树或它的左右两个子树的 ...
- 「FHQ Treap」学习笔记
话说天下大事,就像fhq treap —— 分久必合,合久必分 简单讲一讲.非旋treap主要依靠分裂和合并来实现操作.(递归,不维护fa不维护cnt) 合并的前提是两棵树的权值满足一边的最大的比另一 ...
- Fhq Treap [FhqTreap 学习笔记]
众所周知 Fhq Treap 是 fhq 神仙研究出来的平衡树- 具体实现 每个点实现一个 \(\text{rnd}\) 表示 rand 的值 为什么要 rand 呢 是为了保证树高为 \(\log ...
- 树堆(Treap)学习笔记 2020.8.12
如果一棵二叉排序树的节点插入的顺序是随机的,那么这样建立的二叉排序树在大多数情况下是平衡的,可以证明,其高度期望值为 \(O( \log_2 n )\).即使存在一些极端情况,但是这种情况发生的概率很 ...
随机推荐
- 003_JS基础_面向对象基础
3.1 对象 引入:在js中表示一个人的信息(name, gender, age)通过var申明三个变量,但是这样使用基本数据类型的变量,他们是互相独立的,没有联系: 此时就需要使用对象,对象是 ...
- Reflection and array
java.lang.Reflect.Array类提供了动态创建和访问数组元素的各种静态方法. package com.sunchao.reflection; import java.lang.refl ...
- Spring+redis整合遇到的问题集以及注意事项
redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...
- Fragment禁止预加载
项目中经常会用到ViewPager+Fragment组合,然而,有一个很让人头疼的问题就是,去加载数据的时候由于ViewPager的内部机制所限制,所以它会默认至少预加载一个. 1.既然说是ViewP ...
- error: stray '\357' in program编程出错的总结
错误: 编译报错:error: stray '\357' in program 原因:在程序中打入了全角字符 具体分析产生原因: 在编程中,由于打字的快速,按下ctrl键后紧接着按下了space键 ...
- zabbix agent(Active)模式 /克隆修改模板
这个模式主要是用于server端被动接收数据,不发送探测请求 agent端主动发送数据,不接收探测请求 被监控端 zabbix_Agentd.conf 的配置调整 LogFile=/tmp/zabbi ...
- C# 关键字--virtual(转)
C# 关键字--virtual 一. virtual 关键字用于修饰方法.属性.索引器或事件声明,并使它们可以在派生类中被重写.虚拟成员的实现可由派生类中的重写成员更改,而非虚拟成员是无法由派生类 ...
- bat自动打包压缩实现
1.引言 本文档的编辑目的是为了实bat脚本自动打包功能,包含包的名字命名,压缩文件内外层文件夹的名字:包含svn版本号等: 2.实现介绍 (1)获取svn号,生成批处理文件 写一个pak.bat文件 ...
- JavaScript转unix时间戳
由于 unix 的时间戳是10位不带毫秒的,所以前端获取到时间戳之后需要做一下处理,才能获取正确的时间. // 假设这里是从服务端获取到的时间戳 var unixTime = data.time; / ...
- 16_Python闭包
一.什么是闭包 什么是闭包:内函数对外函数非全局变量的引用,并且外函数的返回值是内函数的引用(地址). def wrapper(): name = 'zhangsan' def inner(): na ...