预备知识:二叉查找树、堆(heap)、平衡二叉树(AVL)的基本操作(左旋右旋)

定义:

Treap。平衡二叉树。Tree+Heap。树堆。

  1. 每个结点两个键值(key、priority)。
  2. 性质1. Treap是关于key的二叉排序树。
  3. 性质2. Treap是关于priority的堆。(非二叉堆,因为不是完全二叉树)
  4. 结论1. key和priority确定时,treap唯一。
  5. 作用1. 随机分配的优先级,使数据插入后更不容易退化为链。就像是将其打乱再插入。所以用于平衡二叉树。

基本操作

要满足它的两个性质,先让它满足二叉排序树的性质,再通过左旋或右旋,来满足堆的性质。

左旋:

下面代码仅为理解用,板子的话就不一样啦:

void Zag(Treap &T){
Treap Q=T->right;
T->right=Q->left;
Q->left=T;
T=Q;
}

右旋:

void Zig(Treap &T){
Treap Q=T->left;
T->left=Q->right;
Q->right=T;
T=Q;
}

插入

  1. 分配一个优先级(用一个随机函数)
  2. 和二叉查找树一样把新结点当叶子插入
  3. 插入后,若破坏堆性质,就把优先级高的旋转上来

复杂度:最多操作次数为树的高度,即O(h),高度期望值=O(logn),故复杂度为O(logn)

删除

优先级有定义(就是key对应的priority不改变):

​ 把要删除的旋转(把俩孩子里优先级高的旋转上来),直到只有一个孩子或者无孩子,直接删去,孩子直接代替自己。

复杂度:旋转1次是O(1),最多h次旋转,故为O(logn)

优先级随机设定:

​ 和普通二叉树删除操作一样,把直接后继或前继结点交换上来,然后删去后续结点。

复杂度:查找直接后继最多O(h),故也是O(logn)

模板

#include <cstdio>
#include <cstdlib>
#define N 100005 using namespace std; int cnt=1,rt=0; //节点编号从1开始
struct Treap{
int key, pri, size, son[2]; //保证父亲的pri大于儿子的pri
}T[N];
void rotate(int p, int &x){
int y=T[x].son[!p];
T[x].size=T[x].size-T[y].size+T[T[y].son[p]].size;
T[x].son[!p]=T[y].son[p];
T[y].size=T[y].size-T[T[y].son[p]].size+T[x].size;
T[y].son[p]=x;
x=y;
}
//插入,调用ins(key,rt)
void ins(int key, int &x){
if(x == 0)
T[x = cnt++]=(Treap){key,rand(),1};
else{
T[x].size++;
int p=key < T[x].key;
ins(key, T[x].son[!p]);
if(T[x].pri < T[T[x].son[!p]].pri)
rotate(p, x);
}
}
//删除,调用del(key,rt)
void del(int key, int &x){
if(T[x].key == key){
if(T[x].son[0] && T[x].son[1]){
int p=T[T[x].son[0]].pri > T[T[x].son[1]].pri;
rotate(p, x);
del(key, T[x].son[p]);
}
else
x=T[x].son[0]?T[x].son[0]:T[x].son[1];
}else{
T[x].size--;
int p=T[x].key > key;
del(key, T[x].son[!p]);
}
}
//找出第p小的节点的编号,第p小的值为T[find(p,rt)].key
int find(int p, int x){
if(p == T[T[x].son[0]].size+1)
return x;
if(p > T[T[x].son[0]].size+1)
return find(p-T[T[x].son[0]].size-1, T[x].son[1]);
else
return find(p, T[x].son[0]);
}
//找出值小于等于key的节点个数
int find_NoLarger(int key, int x){
if(x == 0)
return 0;
if(T[x].key <= key)
return T[T[x].son[0]].size+1+find_NoLarger(key, T[x].son[1]);
else
return find_NoLarger(key, T[x].son[0]);
} int main(){
srand(19970502);
return 0;
}

模板练手题:http://poj.org/problem?id=1442

Treap树 笔记的更多相关文章

  1. bzoj2141 树状数组套Treap树

    题目大意是在能够改变两个数的位置的情况下计算逆序对数 这因为是动态记录逆序对 本来单纯逆序对只要用树状数组计算即可,但这里因为更新,所以利用TReap树的删点和增加点来进行更新 大致是把每个树状数组所 ...

  2. treap树模板

    ///treap树模板 typedef struct Node ///节点的结构体 { Node *l,*r; int val,pri; ///节点的值和优先级 int sz; ///节点子树的节点数 ...

  3. poj 2761 Feed the dogs (treap树)

    /************************************************************* 题目: Feed the dogs(poj 2761) 链接: http: ...

  4. treap树---营业额统计

    台州学院  2924 描述 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况.Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额 ...

  5. treap树---Double Queue

    HDU   1908 Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office i ...

  6. Treap树

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

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

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

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

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

  9. 真·浅谈treap树

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

随机推荐

  1. c++入门之命名空间存在的意义

    看过鸡啄米的C++编程入门系列教程的朋友,应该能注意到,在其中的很多实例中,都有这么一条语句:using namespace std;,即使用命名空间std,其作用就是规定该文件中使用的标准库函数都是 ...

  2. 记一个JS树结构路径查找

    var a=[ { "id" : "0000", "text" : "R1", "children" ...

  3. nginx学习笔记二

    一,nginx架构在Linux系统中以daemon(守护进程)的方式在后台运行,后台进程包含一个master进程和多个worker进程(多进程的工作方式) master进程 | 信号 | | ---- ...

  4. Oracle Profile 配置文件

    Profile是用户的配置文件,它是密码限制,资源限制的命名集合.利用profile 可以对数据库用户进行基本的资源管理,密码管理. 1 创建profile 的语法 create profile pr ...

  5. java编程规范(持续更新)

    1:非空判断 错误例子: if(user.getUserName().equals("hollis")){ } 这段代码极有可能在实际运行的时候跑出NullPointerExcep ...

  6. 428.x的n次幂

    实现 pow(x,n) 不用担心精度,当答案和标准输出差绝对值小于1e-3时都算正确 样例 Pow(2.1, 3) = 9.261 Pow(0, 1) = 0 Pow(1, 0) = 1 挑战 O(l ...

  7. HDU 3900 Unblock Me

    题目:Unblock Me 链接:Here 题意:一个游戏,看图就基本知道题意了,特殊的是:1. 方块长度为3或2,宽度固定是1.2. 地图大小固定是6*6,从0开始. 3. 出口固定在(6,2).4 ...

  8. K8S入门学习

    一.k8s是个什么鬼? k8s全名:kubernetes 它是一个工具,在linux上管理应用生命周期的一个工具. 二.k8s有什么卵用? 1.当你把项目部署到服务器集群上,一台服务器挂了,k8s它可 ...

  9. Web移动端---iPhone X适配(底部栏黑横线)

    一.相信大家有被iPhone X底部黑色横线支配的恐惧 上面我们可以看到,底部的导航栏被一条黑色横线所盖住,那么就很烦.下面我们可以开始进行适配环节 1.首先我们可以用 JS 判断手机环境是不是 iP ...

  10. Kettle中表输出字段和字段选择

    表输出: 字段选择: 注:字段选择可以输出匹配后的选中列,表输出则输出匹配后的所有列.