平衡二叉树 treap 初见

treap通过左右旋维护了一个二叉查找树,根据随机的优先级建立满足优先级大根堆的二叉查找树,在实践中有不错的食府,code也简单。

cogs1829 普通平衡树

题目大意:进行插入、删除、名次、前驱后继。

思路:前面的三种操作都很普通,前驱后继有两种做法(非常不正统吧。。。):1)找到这个数的名次,然后+-1,(如果是后继,并且和原数相同就名次+1,直到不同);2)进行递归查找,以前驱为例:如果这个点的值比x小,就更新一下前驱,找他的右子树,如果>=x,就找他的左子树。这里有可能出现插入多个重复的数,我们可以再开一个域num,记录这种数的个数,然后在操作中相应的进行更改。

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct Node{
    Node *ch[2];
    int r,v,s,num;
    Node(int v):v(v) {ch[0]=ch[1]=NULL;r=rand();s=1;num=1;}
    int cmp(int x) const{
        if (x==v) return -1;
        else return x<v?0:1;
    }
    void Maintain(){
        s=num;
        if (ch[0]!=NULL) s+=ch[0]->s;
        if (ch[1]!=NULL) s+=ch[1]->s;
    }
};
Node* root;
void rotate(Node* &o,int d)
{
    Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->Maintain();k->Maintain();o=k;
}
void insert(Node* &o,int x)
{
    if (o==NULL) o=new Node(x);
    else
    {
        int d=o->cmp(x);
        if (d==-1) ++o->num;
        else
        {
          insert(o->ch[d],x);
          if (o->ch[d] ->r > o->r) rotate(o,d^1);
        }
    }
    o->Maintain();
}
void del(Node* &o,int x)
{
    int d=o->cmp(x);
    if (d==-1)
    {
        if (o->num==1)
        {
          if (o->ch[0]==NULL) o=o->ch[1];
          else
          {
            if (o->ch[1]==NULL) o=o->ch[0];
            else
            {
                int d2=(o->ch[0] ->r > o->ch[1] ->r ? 1 : 0);
                rotate(o,d2);del(o->ch[d2],x);
            }
          }
        }
        else --o->num;
    }
    else del(o->ch[d],x);
    if (o!=NULL) o->Maintain();
}
int rank(Node* &o,int x)
{
    int d=o->cmp(x);
    if (d==-1) return (o->ch[0]==NULL ? 1 : o->ch[0] ->s +1);
    else
    {
        if (d==0) return rank(o->ch[d],x);
        else return rank(o->ch[d],x) + (o->ch[0]==NULL ? o->num : o->ch[0] ->s +o->num);
    }
}
int kth(Node* &o,int x)
{
    if (o==NULL||x<=0||x > o->s) return 0;
    int s=(o->ch[0]==NULL ? 0 : o->ch[0] ->s);
    if (x>=s+1&&x<=s+ o->num) return o->v;
    if (x<=s) return kth(o->ch[0],x);
    else return kth(o->ch[1],x-s- o->num);
}
int main()
{
    freopen("phs.in","r",stdin);
    freopen("phs.out","w",stdout);

    int n,i,j,x,t,k;
    scanf("%d",&n);
    for (i=1;i<=n;++i)
    {
        scanf("%d%d",&j,&x);
        if (j==1)
            insert(root,x);
        if (j==2)
            del(root,x);
        if (j==3)
        {
            t=rank(root,x);
            printf("%d\n",t);
        }
        if (j==4)
        {
            t=kth(root,x);
            printf("%d\n",t);
        }
        if (j==5)
        {
            insert(root,x);
            k=rank(root,x);
            t=kth(root,k-1);
            del(root,x);
            printf("%d\n",t);
        }
        if (j==6)
        {
            insert(root,x);
            k=rank(root,x);
            t=kth(root,k+1);
            while(t==x)
            {
                ++k;t=kth(root,k+1);
            }
            del(root,x);
            printf("%d\n",t);
        }
    }

    fclose(stdin);
    fclose(stdout);
}

1)

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct Node{
    Node *ch[2];
    int r,v,s,num;
    Node(int v):v(v) {ch[0]=ch[1]=NULL;r=rand();s=1;num=1;}
    int cmp(int x) const{
        if (x==v) return -1;
        else return x<v?0:1;
    }
    void Maintain(){
        s=num;
        if (ch[0]!=NULL) s+=ch[0]->s;
        if (ch[1]!=NULL) s+=ch[1]->s;
    }
};
Node* root;
int t;
void rotate(Node* &o,int d)
{
    Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->Maintain();k->Maintain();o=k;
}
void insert(Node* &o,int x)
{
    if (o==NULL) o=new Node(x);
    else
    {
        int d=o->cmp(x);
        if (d==-1) ++o->num;
        else
        {
          insert(o->ch[d],x);
          if (o->ch[d] ->r > o->r) rotate(o,d^1);
        }
    }
    o->Maintain();
}
void del(Node* &o,int x)
{
    int d=o->cmp(x);
    if (d==-1)
    {
        if (o->num==1)
        {
          if (o->ch[0]==NULL) o=o->ch[1];
          else
          {
            if (o->ch[1]==NULL) o=o->ch[0];
            else
            {
                int d2=(o->ch[0] ->r > o->ch[1] ->r ? 1 : 0);
                rotate(o,d2);del(o->ch[d2],x);
            }
          }
        }
        else --o->num;
    }
    else del(o->ch[d],x);
    if (o!=NULL) o->Maintain();
}
int rank(Node* &o,int x)
{
    int d=o->cmp(x);
    if (d==-1) return (o->ch[0]==NULL ? 1 : o->ch[0] ->s +1);
    else
    {
        if (d==0) return rank(o->ch[d],x);
        else return rank(o->ch[d],x) + (o->ch[0]==NULL ? o->num : o->ch[0] ->s +o->num);
    }
}
int kth(Node* &o,int x)
{
    if (o==NULL||x<=0||x > o->s) return 0;
    int s=(o->ch[0]==NULL ? 0 : o->ch[0] ->s);
    if (x>=s+1&&x<=s+ o->num) return o->v;
    if (x<=s) return kth(o->ch[0],x);
    else return kth(o->ch[1],x-s- o->num);
}
void pre(Node* &o,int x)
{
    if (o->v >=x)
    {
       if (o->ch[0]!=NULL) pre(o->ch[0],x);
    }
    else
    {
        t=max(t,o->v);
        if (o->ch[1]!=NULL) pre(o->ch[1],x);
    }
}
void succ(Node* &o,int x)
{
    if (o->v <=x)
    {
      if (o->ch[1]!=NULL) succ(o->ch[1],x);
    }
    else
    {
        t=min(t,o->v);
        if (o->ch[0]!=NULL) succ(o->ch[0],x);
    }
}
int main()
{
    freopen("phs.in","r",stdin);
    freopen("phs.out","w",stdout);

    int n,i,j,x;
    scanf("%d",&n);
    for (i=1;i<=n;++i)
    {
        scanf("%d%d",&j,&x);
        if (j==1)
            insert(root,x);
        if (j==2)
            del(root,x);
        if (j==3)
        {
            t=rank(root,x);
            printf("%d\n",t);
        }
        if (j==4)
        {
            t=kth(root,x);
            printf("%d\n",t);
        }
        if (j==5)
        {
            t=-2100000000;
            pre(root,x);
            printf("%d\n",t);
        }
        if (j==6)
        {
            t=2100000000;
            succ(root,x);
            printf("%d\n",t);
        }
    }

    fclose(stdin);
    fclose(stdout);
}

2)

时间: 2024-10-02 18:41:54

平衡二叉树 treap 初见的相关文章

平衡二叉树

1.基础知识 平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:1.它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.2.其高度一般都良好地维持在O(log2n),大大降低了操作的时间复杂度.3.平衡二叉树的常用算法有红黑树.AVL.Treap等. 4.最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci数列,1是根节点,

平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是将有向树的所有边看成无向边形成的树状图.树是一种递归的数据结构,所以我们研究树也是按照递归的方式去研究的. 2.什么是二叉树. 我们给出二叉树的递归定义如下: (1)空树是一个二叉树. (2)单个节点是一个二叉树. (3)如果一棵树中,以它的左右子节点为根形成的子树都是二叉树,那么这棵树本身也是二叉

非旋转Treap

Treap是一种平衡二叉树,同时也是一个堆.它既具有二叉查找树的性质,也具有堆的性质.在对数据的查找.插入.删除.求第k大等操作上具有期望O(log2n)的复杂度.     Treap可以通过节点的旋转来实现其维持平衡的操作,详见旋转式Treap. 而旋转式Treap在对区间数据的操作上无能为力,这就需要非旋转式Treap来解决这些区间问题. 非旋转式Treap支持的操作 基本操作: 操作 说明 实现复杂度 Build 构造Treap O(n) Merge 合并Treap O(log2n) Sp

好久不见的博客咯!——没有可持久化的可持久化treap

每每想要去了解可持久化treap这个好写好调的东东,然后就发现网上只有一个人的--SymenYang的!在此我必须得把他批判一番--写方法不贴代码是什么心态!而且写出来的是有问题的呀!害人不浅! 好吧说正经事,这个版本的treap名叫可持久化treap却没有可持久化,而是借鉴了可持久化treap中的一些写法.貌似可持久化之后反而难写难调...在这个版本的treap中加入了堆权值来维护树的形状,然后由三种操作--合并(merge),按size拆分(split_size),按值拆分(split_kt

平衡二叉树讲解

注:能用STL就尽量用STL 平衡二叉树(Balanced Binary Tree),又根据它的发明者命名为AVL树. 它或者是一颗空树,或者具有以下性质的二叉树:它的左子树和右子树的深度之差的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树. 平衡因子(bf):结点的左子树的深度减去右子树的深度,那么显然-1<=bf<=1;   相关的算法有红黑树.AVL.Treap.伸展树(Splay).SBT等. 一.AVL算法 直接上图,清晰明了,分类讨论四种情况就行了.   二.伸展树(Spl

7. 蛤蟆的数据结构进阶七平衡二叉树

7. 蛤蟆的数据结构进阶七平衡二叉树 本地名言:"金钱的贪求(这个毛病,目前我们大家都犯得很凶)和享乐的贪求,促使我们成为它们的奴隶,也可以说,把我们整个身心投入深渊.唯利是图,是一种痼疾,使人卑鄙,但贪求享乐,更是一种使人极端无耻,不可救药的毛病. --郎加纳斯" 我们来看下传说中的平衡二叉树,为什么说他传说中呢?因为蛤蟆接触ORACLE数据库比较多,而ORACLE数据中用到最多的索引就是平衡二叉树,所以嘛. 欢迎转载,转载请标明出处:http://write.blog.csdn.n

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

使用STL来模拟Treap的功能

问题描述 我们知道,Treap可以完成节点的动态插入.删除.查询,其每个操作的时间复杂度是O(log n),因为其实现较红黑树更为简单,因此常常用于某些场合,以替换红黑树的实现. Treap的每个节点维护了key, priority. struct Node { int key; int priority; Node (int k, int p): key(k), priority(p) {} } key是作为BST的键值,用于支持快速的插入.删除和查询操作,而priority则是用于维护最小堆

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

原文:6天通吃树结构-- 第三天 Treap树 我们知道,二叉查找树相对来说比较容易形成最坏的链表情况,所以前辈们想尽了各种优化策略,包括AVL,红黑,以及今天 要讲的Treap树. Treap树算是一种简单的优化策略,这名字大家也能猜到,树和堆的合体,其实原理比较简单,在树中维护一个"优先级“,”优先级“ 采用随机数的方法,但是”优先级“必须满足根堆的性质,当然是“大根堆”或者“小根堆”都无所谓,比如下面的一棵树: 从树中我们可以看到: ①:节点中的key满足“二叉查找树”. ②:节点中的“优