Treap 动态平衡树

(注:本文是笔者在学习Treap的时候的一点收获,并将一些基础知识记录下来)

Treap

定义:

treap是一中动态平衡的BST,可以高效地处理插入和删除等,是一棵有键值和优先值的树。

一些小笔记:

(我刚学c++是很讨厌指针,但学到Treap时竟然可以接受了,O(∩_∩)O~~)

初始定义

struct node{
    char *ch[2];//左右子树
    int r;//随机的优先值
    int v;//值
    int s;//以这个节点为根的节点总数

    int cmp(int x)
    {
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }

    void maintain()//用于更新s
    {
        s = 1;
        if(ch[0] != NULL) s += ch[0]->s;
        if(ch[1] != NULL) s += ch[1]->s;
    }
};

旋转

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;
}
//then change rotate
void rotate(node* &o,int d)//加上maintain的旋转 
{
    node* k = o->ch[d^1];
    o->ch[d^1] = k->ch[d];
    k->ch[d] = o;
    o->maintain();
    k->maintain();//先更新o,再更新k 
    o = k;
}

插入

void insert(node* &o,int x)
{
    if(o == NULL)
    {
        o = new node();
        o->ch[0] = o->ch[1] = NULL;
        o->v = x;
        o->rand();
    }
    else
    {
        int d = o->cmp(x);//注意有没有相同的结点 
        insert(o->ch[d],x);
        if(o->ch[d]->r > o->r) rotate(o,d^1);
    }
}

删除

void remove(node* &o,int x)//删除结点 
{
    int d = o->cmp(x);
    if(d == -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);
            remove(o->ch[d2],x);
        }//将左右子树的根中优先级高的旋转上来,再继续删点 
    }
    else remove(o->ch[d],x);
}

查询

int find(node* o,int x)//在每次操作前可以查询这个点是否存在 
{
    while(o != NULL)
    {
        int d = o->cmp(x);
        if(d == -1) return -1;//存在 
        else o = o->ch[d];
    }
    return 0;//不存在 
} 

Kth

int kth(node* o,int k)//找第k大的值 
{
    if(o == NULL || k <= 0 || k > o->s) return 0;
    int s = (o->ch[0] == NULL ? 0 : o->ch[0]->s;
    if(k == s+1) return o->v;
    else 
        if(k <= s) return kth(o->ch[0],k);
            else return kth(o->ch[1],k-s-1);
}

这是我所偏好的代码风格。。。

然后还有一道很妙的例题,叫:LA-5031,感觉很复杂O(∩_∩)O~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值