平衡树

简介:

平衡二叉树(Balanced Binary Tree)具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

Treap:

简介:

Treap代码实现相对简单的一个算法,Treap是 heap+Tree,既满足堆的性质也满足平衡树的性质,一棵树的节点上有一个data用于存数据,fix是一个堆的优先级(假设我们是小顶堆),key是平衡树的比较值;key一般是给出的,然而fix我们随机生成,这样的随机会使得平衡树比较平衡。假设一棵排序二叉树插入一组有序的数,就会使得树退化为一条链。我们在插入的时候为每个节点随机生成一个fix(优先级)。插入时满足排序二叉树的性质。插入完成时检查是否满足堆的性质,并进行旋转操作使他满足堆的性质。

旋转操作:

为了满足堆的性质,我们需要对这棵树进行旋转以达到堆的性质。旋转操作看图
如图是旋转操作,我用的是指针链式的写法:所以,每次旋转需要调整两个节点的父子关系。以及指向P或者Q的那个指针。
下面给出指针的写法
void rotate(Node* &o,int d)
{
Node *k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o=k;
}

上面是旋转操作,d传0代表左旋,d为1代表右旋;

当我们了解旋转操作后,接下来;

插入元素操作:

首先根据排序二叉树的性质找到叶子节点,将新的元素插入到叶子节点。当插入之后会破坏堆的性质,然后进行旋转操作让他满足堆的性质,因为那样旋转不会破坏排序二叉树的性质的。所以旋转只需要考虑堆的性质。

删除操作:

用排序二叉树的性质去找要删除的元素位置,找到之后判断是否左右都是有儿子,如果不是直接删除,把指向他的指针,直接指向他的儿子节点。如果是就需要通过旋转操作。把需要删除的元素往下旋转。旋转时为了满足堆的性质(如果是小顶堆)需要比较左右儿子的大小,将该元素与小值的儿子进行旋转。
 
 #include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int sz;
const int maxn=1e6+;
struct Node
{
Node *ch[];
int r,v,info;//v是顾客优先级,info是顾客的编号,r由rand()生成
int cmp(int x)
{
if(x==v) return -;
return x<v? :;
}
}T[maxn];
Node * newnode(int _v,int _info)
{
Node *res=&T[sz];
T[sz].v=_v,T[sz].info=_info;
T[sz].r=rand();
T[sz].ch[]=T[sz].ch[]=NULL;
sz++;
return res;
}
void rotate(Node* &o,int d)
{
Node *k=o->ch[d^];
o->ch[d^]=k->ch[d];
k->ch[d]=o;
o=k;
}
void insert(Node* &o,int v,int info)
{
if(o==NULL) o=newnode(v,info);
else
{
int d= v < o->v?:;
insert(o->ch[d],v,info);
if(o->ch[d]->r > o->r)
rotate(o,d^);
}
}
void remove(Node *&o,int v)
{
int d=o->cmp(v);
if(d==-)
{
if(o->ch[] && o->ch[])
{
int d2 = o->ch[]->r < o->ch[]->r ?:;
rotate(o,d2);
remove(o->ch[d2],v);
}
else
{
if(o->ch[]==NULL)o=o->ch[];
else o=o->ch[];
}
}
else remove(o->ch[d],v);
}
int find_max(Node *o)//找到最大v值
{
if(o->ch[]==NULL)
{
printf("%d\n",o->info);
return o->v;
}
return find_max(o->ch[]);
}
int find_min(Node *o)//找到最小v值
{
if(o->ch[]==NULL)
{
printf("%d\n",o->info);
return o->v;
}
return find_min(o->ch[]);
}
int main()
{
int op;
Node *root=NULL;
sz=;
while(scanf("%d",&op)==&&op)
{
if(op==)
{
int info,v;
scanf("%d%d",&info,&v);
insert(root,v,info);
}
else if(op==)
{
if(root==NULL)
{
printf("0\n");
continue;
}
int v=find_max(root);
remove(root,v);
}
else if(op==)
{
if(root==NULL)
{
printf("0\n");
continue;
}
int v=find_min(root);
remove(root,v);
}
}
return ;
}
 
优先队列的实现。

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

  1. 【数据结构】【平衡树】浅析树堆Treap

    [Treap] [Treap浅析] Treap作为二叉排序树处理算法之一,首先得清楚二叉排序树是什么.对于一棵树的任意一节点,若该节点的左子树的所有节点的关键字都小于该节点的关键字,且该节点的右子树的 ...

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

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

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

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

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

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

  5. hihocoder 1193 树堆 解题报告

    题目大意:给出一棵有根树(根为 \(0\) ),点有点权.可以删除点(非根),并将其子树接到其父亲上.我们称一个树为树堆当前仅当树上每个点都满足其权值大于等于其子树中所有点的点权.现在对于每个点要求其 ...

  6. Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6471  Solved: 2697[Su ...

  7. BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】

    BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...

  8. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  9. 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap

    题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义 ...

随机推荐

  1. HTML5 一些有用的 APIs

    Animation Timing Window.requestAnimationFrame(callback): 告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘(类似于 setTi ...

  2. 正确使用Block避免Cycle Retain和Crash

    Block简介 Block作为C语言的扩展,并不是高新技术,和其他语言的闭包或lambda表达式是一回事.需要注意的是由于Objective-C在iOS中不支持GC机制,使用Block必须自己管理内存 ...

  3. 调用tensorflow中的concat方法时Expected int32, got list containing Tensors of type '_Message' instead.

    grid = tf.concat(0, [x_t_flat, y_t_flat, ones])#报错语句 grid = tf.concat( [x_t_flat, y_t_flat, ones],0) ...

  4. dubbo开发者指南

    开发者指南 参与 流程 任务 版本管理 源码构建 框架设计 整体设计 模块分包 依赖关系 调用链 暴露服务时序 引用服务时序 领域模型 基本原则 扩展点加载 扩展点配置 扩展点自动包装 扩展点自动装配 ...

  5. Redis 数据结构解析和命令指南

    命令參考文档:redis commands - 你或许已经知道Redis并非简单的key-value存储.实际上他是一个数据结构server.支持不同类型的值. 也就是说.你不必只把字符串当作键所指向 ...

  6. Linux 网卡驱动学习(二)(网络驱动接口小结)

    [摘要]前文我们分析了一个虚拟硬件的网络驱动例子,从中我们看到了网络设备的一些接口,其实网络设备驱动和块设备驱动的功能比较类似,都是发送和接收数据包(数据请求).当然它们实际是有很多不同的. 1.引言 ...

  7. 【Nginx】开发一个HTTP过滤模块

    与HTTP处理模块不同.HTTP过滤模块的工作是对发送给用户的HTTP响应做一些加工. server返回的一个响应能够被随意多个HTTP过滤模块以流水线的方式依次处理.HTTP响应分为头部和包体,ng ...

  8. 不错.net图片水印类

    using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Draw ...

  9. 大型视频网站YouTube架构学习笔记

    http://www.kaiyuanba.cn/html/1/131/147/7540.htm这几天一直在关注和学习一些大型网站的架构,希望有一天自己也能设计一个高并发.高容错的系统并能应用在实践上. ...

  10. VM(转)

    vmplayer  &&  VMworkstation 很多人想尝试一下多种不同的操作系统,例如学习Linux:又或者希望搞一个专门的系统用来测试各种各样东西而不会搞乱搞坏现有的系统. ...