ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

平衡树——Treap

2021-03-05 23:04:56  阅读:204  来源: 互联网

标签:return get int tr rank Treap key 平衡


平衡树——Treap

一、简介

​ 平衡树Treap是由二叉搜索树(BST—“Binary Search Tree”)和堆(Heap)结合而成的数据结构

本质:动态维护一个有序序列

​ 补充BST:当前节点左子树中的任何一个节点的权值均严格小于当前节点的权值,右子树中的任何一个节点的权值均严格大于当前节点的权值。其中序遍历的结果是从小到大的有序序列

Treap的相关操作:

  1. 插入一个数

  2. 删除一个数

  3. 找前驱/后继

    前驱/后继:中序遍历的前/后位置

    前驱:左子树的最大值、第一个左拐弯的祖宗节点

    后继:右子树的最小值、第一个右拐弯的祖宗节点

  4. 找最值

    以上操作set均支持

  5. 求某个值的排名

  6. 求排名为k的数

  7. 求比某数小的最大数

  8. 求比某数大的最小数

Treap的原理:数据本身越有序,树的深度就越大,复杂度会从O(logn)退化到O(n)。可以将BST加入Heap的属性,让其变得尽量随机。

二、基本操作模板

例题链接:253. 普通平衡树

int root, idx;

struct Node
{
    int l, r;
    int key, val;//val为大根堆的关键字,是一个随机值
    int cnt, size;
}tr[N];
//由子节点计算父节点
void pushup(int p)
{
    tr[p].size = tr[tr[p].l].size + tr[tr[p].r].size + tr[p].cnt;
}
//新建节点
int get_node(int key)
{
    tr[++idx].key = key;
    tr[idx].val = rand();
    tr[idx].cnt = tr[idx].size = 1;
    return idx;
}
//右旋
void zig(int &p)
{
    int q = tr[p].l;
    tr[p].l = tr[q].r, tr[q].r = p, p = q;
    pushup(p), pushup(tr[p].r);
}
//左旋
void zag(int &p)
{
    int q = tr[p].r;
    tr[p].r = tr[q].l, tr[q].l = p, p = q;
    pushup(p), pushup(tr[p].l);
}
//建树
void build()
{
    get_node(-INF), get_node(INF);
    root = 1, tr[root].r = 2;
    pushup(root);
    
    if(tr[2].val > tr[1].val) zag(root);
}
//插入操作
void insert(int &p, int key)
{
    if(!p) p = get_node(key);
    else if(tr[p].key == key) tr[p].cnt++;
    else if(tr[p].key > key)
    {
        insert(tr[p].l, key);
        if(tr[tr[p].l].val > tr[p].val) zig(p);
    }
    else
    {
        insert(tr[p].r, key);
        if(tr[tr[p].r].val > tr[p].val) zag(p);
    }
    
    pushup(p);
}
//删除操作
void remove(int &p, int key)
{
    if(!p) return;
    if(tr[p].key == key)
    {
        if(tr[p].cnt > 1) tr[p].cnt--;
        else if(tr[p].l || tr[p].r)
        {
            if(!tr[p].r || tr[tr[p].l].val > tr[tr[p].r].val)
            {
                zig(p);
                remove(tr[p].r, key);
            }
            else
            {
                zag(p);
                remove(tr[p].l, key);
            }
        }
        else p = 0;
    }
    else if(tr[p].key > key) remove(tr[p].l, key);
    else remove(tr[p].r, key);
    
    pushup(p);
}
//通过数值找排名
int get_rank_by_key(int p, int key)
{
    if(!p) return 0;
    if(tr[p].key == key) return tr[tr[p].l].size + 1;
    if(tr[p].key > key) return get_rank_by_key(tr[p].l, key);
    return tr[tr[p].l].size + tr[p].cnt + get_rank_by_key(tr[p].r, key);
}
//通过排名找数值
int get_key_by_rank(int p, int rank)
{
    if(!p) return INF;
    if(tr[tr[p].l].size >= rank) return get_key_by_rank(tr[p].l, rank);
    if(tr[tr[p].l].size + tr[p].cnt >= rank) return tr[p].key;
    return get_key_by_rank(tr[p].r, rank - tr[tr[p].l].size - tr[p].cnt);
}
//找严格小于key的最大数
int get_prev(int p, int key)
{
    if(!p) return -INF;
    if(tr[p].key >= key) return get_prev(tr[p].l, key);
    return max(tr[p].key, get_prev(tr[p].r, key));
}
//找严格大于key的最小数
int get_nect(int p, int key)
{
    if(!p) return INF;
    if(tr[p].key <= key) return get_next(tr[p].r, key);
    return min(tr[p].key, get_next(tr[p].l, key));
}

三、相关例题

265. 营业额统计

标签:return,get,int,tr,rank,Treap,key,平衡
来源: https://www.cnblogs.com/grain-rain/p/14488911.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有