treap 排序二叉树的模板

本文介绍了一种使用Treap数据结构实现支持多种操作的高效算法,包括插入、删除、查找前驱后继元素等。通过具体示例展示了如何利用Treap解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Description
有一个序列含有一定数量的元素,现在要求写一个程序,满足以下几个要求:
【A】支持插入操作(这个序列不允许有重复元素,即是说,如果待插入的元素已经出现在这个序列中,那么请忽略此操作)
【B】支持删除操作(如果此序列中不包含待删除的这个元素,则忽略此操作,否则删除这个元素)
【C】查找元素x的前继元素(前继元素是指:小于x且与x最接近的元素,当然,如果x已经是序列中的最小元素,则x没有前继元素)
【D】查找元素x的后继元素(后继元素是指:大于x且与x最接近的元素,当然,如果x已经是序列中的最大元素,则x没有后继元素)
【E】找第K小的元素
【F】求某个元素x的秩(即x的排名是多少,从小到大排序)
多组数据(整个文件以输入 -1 结束)
对于每组数据,有若干行(最多100000行),表示的意义如下:
【A】 insert x  
【B】 delete x
【C】 predecessor x
【D】 successor x
【E】 Kth x
【F】 rank x
这6种操作的意义与上面的定义相对应!
【G】 print  表示从小到大输出序列中的所有元素
【H】 end	表示结束本组数据
	
每组输入数据后有一空行!
对于以上8种操作,分别输出对应信息,如下:
【A】 insert x  不用输出任何信息
【B】 delete x  如果x存在,则删除x,否则输出 Input Error
【C】 predecessor x  如果x不存在,输出 Input Error;否则如果x是序列中的最小元素,输出对应信息(见样例),否则输出x的前继元素
【D】 successor x    如果x不存在,输出 Input Error;否则如果x是序列中的最大元素,输出对应信息(见样例),否则输出x的后继元素
【E】 Kth x  如果x不合法,输出 Input Error;否则输出第Kth小的元素(见样例)
【F】 rank x  如果x不存在,输出 Input Error;否则输出x的排名(见样例)
【G】 print  从小到大输出序列中的所有元素,每个元素后加一个逗号,并在最后加上 end of print(见样例)
【H】 end	输出 end of this test
insert 20
insert 5
insert 1
insert 15
insert 9
insert 25
insert 23
insert 30
insert 35
print
Kth 0
Kth 1
Kth 3
Kth 5
Kth 7
Kth 9
Kth 10
rank 1
rank 3
rank 5
rank 15
rank 20
rank 30
rank 31
rank 35
successor 15
successor 35
successor 25
successor 26
predecessor 1
predecessor 20
predecessor 23
predecessor 15
predecessor 111
delete 9
delete 15
delete 25
delete 23
delete 20
print
Kth 3
Kth 4
rank 30
rank 35
end

-1
1,5,9,15,20,23,25,30,35,end of print
Input Error
The 1_th element is 1
The 3_th element is 9
The 5_th element is 20
The 7_th element is 25
The 9_th element is 35
Input Error
The rank of 1 is 1_th
Input Error
The rank of 5 is 2_th
The rank of 15 is 4_th
The rank of 20 is 5_th
The rank of 30 is 8_th
Input Error
The rank of 35 is 9_th
The successor of 15 is 20
35 is the maximum
The successor of 25 is 30
Input Error
1 is the minimum
The predecessor of 20 is 15
The predecessor of 23 is 20
The predecessor of 15 is 9
Input Error
1,5,30,35,end of print
The 3_th element is 30
The 4_th element is 35
The rank of 30 is 3_th
The rank of 35 is 4_th
end of this test
 
   
 
   
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<map>
#include<string>
using namespace std;
#define nn 200005
#define inf 0x7ffff

struct treap
{
    int sz,key,fix,num;
    treap *ch[2];
    treap(int key)
    {
        sz=1;
        num=1;
        fix=rand();
        this->key=key;
        ch[0]=ch[1]=0;
    }
    int compare(int x) const
    {
        if(x==key) return -1;
        return x<key?0:1;
    }
    void maintain()
    {
        sz=num;
        if(ch[0]!=0) sz+=ch[0]->sz;
        if(ch[1]!=0) sz+=ch[1]->sz;
    }
};
treap* root;
void rotate(treap* &t,int d)//旋转
{
    treap *k=t->ch[d^1];
    t->ch[d^1]=k->ch[d];
    k->ch[d]=t;
    t->maintain();
    k->maintain();
    t=k;
}

void insert(treap* &t,int x)//添加
{
    if(t==0) t=new treap(x);
    else
    {
        int d=x<t->key?0:1;
        insert(t->ch[d],x);
        if(t->ch[d]->fix>t->fix)
            rotate(t,d^1);
    }
    t->maintain();
}
void Delete(treap* &t,int x)//删除
{
    int d=t->compare(x);
    if(d==-1)
    {
        treap *tmp=t;
        if(t->ch[0]==0)
        {
            t=t->ch[1];
            delete tmp;
            tmp=0;
        }
        else if(t->ch[1]==0)
        {
            t=t->ch[0];
            delete tmp;
            tmp=0;
        }
        else
        {
            int k=t->ch[0]->fix>t->ch[1]->fix?1:0;
            rotate(t,k);
            Delete(t->ch[k],x);
        }
    }
    else Delete(t->ch[d],x);
    if(t!=0) t->maintain();
}

bool Find(treap *t,int x)//查找
{
    while(t!=0)
    {
        int d=t->compare(x);
        if(d==-1) return true;
        t=t->ch[d];
    }
    return false;
}

int kth(treap *t,int k)//找第K小的元素
{
    if(t==0||k<=0||k>t->sz)
        return -1;
    if(t->ch[0]==0&&k==1)
        return t->key;
    if(t->ch[0]==0)
        return kth(t->ch[1],k-1);
    if(t->ch[0]->sz>=k)
        return kth(t->ch[0],k);
    if(t->ch[0]->sz+1==k)
        return t->key;
    return kth(t->ch[1],k-1-t->ch[0]->sz);
}

int Rank(int x) //x的排名是多少,从小到大排序
{
    int ans=0;
    treap* p=root;
    while(1)
    {
        if(p->key==x)
        {
            ans+=1+(p->ch[0]?p->ch[0]->sz:0);
            break;
        }
        else if(x<p->key)
            p=p->ch[0];
        else
        {
            ans+=p->num+(p->ch[0]?p->ch[0]->sz:0);
            p=p->ch[1];
        }
    }
    return ans;
}

int depth(treap *t)
{
    if(t==0) return -1;
    int l=depth(t->ch[0]);
    int r=depth(t->ch[1]);
    return l<r?(r+1):(l+1);
}

void delettreap(treap* &t)//释放空间
{
    if(t==0) return;
    if(t->ch[0]!=0) delettreap(t->ch[0]);
    if(t->ch[1]!=0) delettreap(t->ch[1]);
    delete t;
    t=0;
}

void Print(treap *t)//打印树,从小到大
{
    if(t==0) return;
    Print(t->ch[0]);
    printf("%d,",t->key);
    Print(t->ch[1]);
}
int pre(int x)
{
    treap* p=root;
    int ans=0;
    bool fuck=0;
    while(p)
    {
        if(p->key<x)
        {
            ans=p->key;
            fuck=1;
        }
        p=p->ch[p->key<x];
    }
    if(fuck) return ans;
    return inf;
}
int suc(int x)
{
    treap* p=root;
    int ans=0;
    bool fuck=0;
    while(p)
    {
        if(p->key>x)
        {
            ans=p->key;
            fuck=1;
        }
        p=p->ch[p->key<=x];
    }
    if(fuck) return ans;
    return inf;
}
int main()
{
    int n,m;
    char op[30];
    while(~scanf("%s",op))
    {
        if(strcmp(op,"-1")==0)
            break;
        if(op[0]=='e')
        {
            puts("end of this test");
            delettreap(root);
            continue;
        }
        if(op[0]=='p'&&op[2]=='i')
        {
            Print(root);
            puts("end of print");
        }
        else
        {
            int x;
            scanf("%d",&x);
            if(op[0]=='i')
            {
                if(!Find(root,x))
                    insert(root,x);
            }
            else if(op[0]=='d')
            {
                if(Find(root,x))
                    Delete(root,x);
                else printf("Input Error\n");

            }
            else if(op[0]=='p'&&op[2]=='e')
            {
                if(Find(root,x))
                {
                    int y=pre(x);
                    if(y<inf) printf("The predecessor of %d is %d\n",x,y);
                    else printf("%d is the minimum\n",x);
                }
                else
                    printf("Input Error\n");
            }
            else if(op[0]=='s')
            {
                if(Find(root,x))
                {
                    int y=suc(x);
                    if(y<inf) printf("The successor of %d is %d\n",x,y);
                    else printf("%d is the maximum\n",x);
                }
                else
                    printf("Input Error\n");
            }
            else if(op[0]=='K')
            {
                int y=kth(root,x);
                if(y==-1) printf("Input Error\n");
                else printf("The %d_th element is %d\n",x,y);
            }
            else if(op[0]=='r')
            {
                if(!Find(root,x))
                    printf("Input Error\n");
                else printf("The rank of %d is %d_th\n",x,Rank(x));
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值