Treap简介

来源:互联网 发布:剑指offer python 编辑:程序博客网 时间:2024/06/17 18:39

定义

树堆,在数据结构中也称Treap,是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。

简单点说,Treap=tree+heap

实现

Treap实际上是对BST的优化。因为BST有可能退化成链而导致查询复杂度变成O(n),而Treap多了heap这个性质,使得它的期望复杂度可以达到O(nlog2n)

而维护heap时需要旋转操作,这里给一张图体会一下:

这里写图片描述

那heap这个性质是怎么来的呢?

在插入一个节点时,我们随机地给它一个优先级,然后和维护heap一样维护这个优先级。插入时如果优先级比根大就旋转。删除时和插入反过来就可以了,把需要删除的节点不断旋转至叶子节点,然后删去即可。

操作

由于Treap的本质就是BST,因此它支持BST的所有操作。

代码实现(模板)

以BZOJ3224(洛谷P3369)为例:

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#define N 100000using namespace std;struct node{    int w,p,size,rnd,to[2];    //w:权值 p:有多少权值是相等的 size:子树中的节点个数    //rnd:优先级 to[]:儿子}t[N+5];int n,rt,nd,p;void rtt(int &x,int fl){//rotate(旋转)    int s=t[x].to[fl];    t[x].to[fl]=t[s].to[fl^1];    t[s].to[fl^1]=x;    t[s].size=t[x].size;    t[x].size=t[t[x].to[0]].size+t[t[x].to[1]].size+t[x].p;    x=s; return;}void nsrt(int &x,int w){//insert(插入)    if (!x){        t[x=++nd].w=w;         t[x].rnd=rand();        t[x].p=t[x].size=1;        return;    }    t[x].size++;    if (t[x].w==w) t[x].p++;    else if (t[x].w<w){        nsrt(t[x].to[1],w);        if (t[t[x].to[1]].rnd<t[x].rnd) rtt(x,1);    }    else{        nsrt(t[x].to[0],w);        if (t[t[x].to[0]].rnd<t[x].rnd) rtt(x,0);    }}void dlt(int &x,int w){//delete(删除)    if (!x) return;    if (t[x].w==w){        if (t[x].p>1){ t[x].p--; t[x].size--; return; }        if (!(t[x].to[0]*t[x].to[1])) x=t[x].to[0]+t[x].to[1];        else if (t[t[x].to[0]].rnd<t[t[x].to[1]].rnd) rtt(x,0),dlt(x,w);        else rtt(x,1),dlt(x,w);    }    else{        t[x].size--;        if (t[x].w<w) dlt(t[x].to[1],w);        else dlt(t[x].to[0],w);    }}int srch_rk(int x,int w){//search_rank(查询排名)    if (!x) return 0;    if (t[x].w==x) return t[t[x].to[0]].size+1;    else if (t[x].w<w)        return t[t[x].to[0]].size+t[x].p+srch_rk(t[x].to[1],w);    else return srch_rk(t[x].to[0],w);}int srch_nm(int x,int w){//search_num(查询数)    if (!x) return 0;    if (t[t[x].to[0]].size>=w)        return srch_nm(t[x].to[0],w);    else if (t[t[x].to[0]].size+t[x].p<w)        return srch_nm(t[x].to[1],w-t[t[x].to[0]].size-t[x].p);    else return t[x].w;}int srch_frnt(int x,int w){//search_front(查询前驱)    if (!x) return 0;    if (t[x].w<w){        int k=srch_frnt(t[x].to[1],w);        if (!k) return t[x].w;        else return k;    }    else return srch_frnt(t[x].to[0],w);}int srch_bck(int x,int w){//search_back(查询后继)    if (!x) return 0;    if (t[x].w>w){        int k=srch_bck(t[x].to[0],w);        if (!k) return t[x].w;        else return k;    }    else return srch_bck(t[x].to[1],w);}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++){        int flag,x;         scanf("%d%d",&flag,&x);        switch (flag){            case 1: nsrt(rt,x); break;            case 2: dlt(rt,x); break;            case 3: printf("%d\n",srch_rk(rt,x)+1); break;//这里记得+1            case 4: printf("%d\n",srch_nm(rt,x)); break;            case 5: printf("%d\n",srch_frnt(rt,x)); break;            case 6: printf("%d\n",srch_bck(rt,x)); break;        }    }    return 0;}
原创粉丝点击