码迷,mamicode.com
首页 > 其他好文 > 详细

平衡二叉树 treap 初见

时间:2015-01-10 10:03:48      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:

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)

 

平衡二叉树 treap 初见

标签:

原文地址:http://www.cnblogs.com/Rivendell/p/4214488.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!