Treap(树堆)

一、Treap简介

Treap 是一种具有堆性质的二叉搜索树
原理:为每一个结点赋予一个随机值使其满足堆的性质,
保证树高度在O(logN)左右,以此保证较低的时间复杂度

Treap和set比较
Treap比set更好实现
Treap更易于处理类似第K性质的求解问题,而set实现起来稍逊一筹
综上述,Treap常用于算法竞赛需要手写BST的时候,尤其是名次树

二、实现

#include<iostream>
#include<algorithm>
using namespace std;

const int maxNode = 1<<15;
const int INF = 0x3f3f3f3f;

class Treap
{
    int root, treapCnt, key[maxNode], priority[maxNode], childs[maxNode][2], cnt[maxNode], size[maxNode];

    int rand()
    {
        static int seed = 2333;
        return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
    }

    //旋转
    void rotate(int& x, int t)
    {
        int y = childs[x][t];
        childs[x][t] = childs[y][1 - t];
        childs[y][1 - t] = x;
        update(x);
        update(y);
        x = y;
    }

    //更新规模大小
    void update(const int x)
    {
        size[x] = size[childs[x][0]] + cnt[x] + size[childs[x][1]];
    }

    //插入k值
    void _insert(int& x, const int k)
    {
        if (x)
        {
            if (key[x] == k)
            {
                cnt[x]++;                   //如果该键值存在,那么数量+1
            }
            else
            {
                bool t = key[x] < k;         //判断k应属的子树
                _insert(childs[x][t], k);
                if (priority[childs[x][t]] < priority[x])
                {
                    rotate(x, t);
                }
            }
        }
        else
        {
            x = treapCnt++;
            key[x] = k;
            cnt[x] = 1;
            priority[x] = rand();
            childs[x][0] = childs[x][1] = 0;
        }
        update(x);
    }

    void _erase(int& x, const int k)
    {
        if (key[x] == k)
        {
            if (cnt[x] > 1)
                cnt[x]--;
            else
            {
                if (childs[x][0] == 0 && childs[x][1] == 0)
                {
                    x = 0;
                    return;
                }
                int t = priority[childs[x][0]] > priority[childs[x][1]];
                rotate(x, t);
                _erase(x, k);
            }
        }
        else
        {
            _erase(childs[x][key[x] < k], k);
        }
        update(x);
    }

    int _getKth(int& x, int k, const bool ismax)
    {
        if (k <= size[childs[x][ismax]])
        {
            return _getKth(childs[x][ismax], k, ismax);
        }
        k -= size[childs[x][ismax]] + cnt[x];
        if (k <= 0)
            return key[x];
        return _getKth(childs[x][!ismax], k, ismax);
    }

    int _findRank(const int p, const int x)
    {
        if (!p)return 0;
        if (key[p] == x)return size[childs[p][0]] + 1;
        if (x > key[p])return size[childs[p][0]] + cnt[p] + _findRank(childs[p][1], x);
        else return _findRank(childs[p][0], x);
    }

    int _findBack(const int p, const int x)
    {
        if (!p)return -INF;
        if (key[p] < x)return max(key[p], _findBack(childs[p][1], x));
        else if (key[p] >= x)return _findBack(childs[p][0], x);
    }

    int _findFront(const int p, const int x)
    {
        if (!p)return INF;
        if (key[p] <= x)return _findFront(childs[p][1], x);
        else return min(key[p], _findFront(childs[p][0], x));
    }
public:

    Treap()
    {
        root = 0;
        treapCnt = 1;
        priority[0] = INF;
        size[0] = 0;
    }

    //插入键值k
    void insert(const int k)
    {
        _insert(root, k);
    }

    //删除键值k
    void erase(const int k)
    {
        _erase(root, k);
    }

    //查询 K-th
    int getKth(const int k, const bool ismax)
    {
        return _getKth(root, k, ismax);
    }

    //查询x的排名
    int find_rank(const int x)
    {
        return _findRank(root, x);
    }

    //查询键值x的前驱
    int find_back(const int x)
    {
        return _findBack(root, x);
    }

    //查询键值x的后继
    int find_front(const int x)
    {
        return _findFront(root, x);
    }
};
原文地址:https://www.cnblogs.com/bryce1010/p/9386974.html