zoukankan      html  css  js  c++  java
  • 具有随机性的平衡树——treap

    简而言之,treap=tree+heap,首先它是一棵二叉树,其次treap中每个节点含有一个优先级的值,这些值随机给定,但整棵树中的这些值满足大根堆(或小根堆的性质)。

    左旋与右旋操作跟其他平衡树一样。

    插入操作:首先将新节点插入到叶子节点位置(与普通排序二叉树一样),然后由于插入后可能破坏了heap的性质,这个时候需要对新插入节点的根节点进行左旋或右旋,一直调整到符合heap性质为止。

    删除操作:将需要删除的节点旋转到叶子节点或者只有一个孩子的位置,然后删掉就可以了。

    关于size,用treap来维护节点的size域(即以某节点为根的子树中节点的个数)是非常方便的,加一个maintain操作即可。

    // 不带size域的treap
    class Treap {
    public:
        const static int MaxN = 100000;
        int root, tsize, l[MaxN], r[MaxN], p[MaxN];
        int key[MaxN];
    
        void rot_l(int &x) {    //before using this function, please ensure that the right son of x exist
            int tmp = r[x];
            r[x] = l[tmp]; l[tmp] = x;
            x = tmp;
        }
        void rot_r(int &x) {    //before using this function, please ensure that the left son of x exist
            int tmp = l[x];
            l[x] = r[tmp]; r[tmp] = x;
            x = tmp;
        }
        Treap():root(-1),tsize(-1) {}
        void insert(int &root, const int &x) {
            if(root == -1) {
                key[++tsize] = x;
                root = tsize;
                p[root] = rand();
                l[root] = r[root] = -1;
            }
            else if(x <= key[root]) {
                insert(l[root], x);
                if(p[l[root]] > p[root])  rot_r(root);
            }
            else {
                insert(r[root], x);
                if(p[r[root]] > p[root])  rot_l(root);
            }
        }
        void del(int &root, const int &x) {
            if(key[root] == x) {
                if(l[root]==-1 && r[root]==-1)  root = -1;
                else if(l[root] == -1)  root = r[root];
                else if(r[root] == -1)  root = l[root];
                else {
                    if(p[l[root]] > p[r[root]]) {
                        rot_r(root);
                        del(r[root], x);
                    }
                    else {
                        rot_l(root);
                        del(l[root], x);
                    }
                }
            }
            else if(x < key[root])  del(l[root], x);
            else del(r[root], x);
        }
        bool find(int &root, const int &x) {
            if(root == -1)  return  false;
            if(x == key[root])  return  true;
            else if(x < key[root])  return  find(l[root], x);
            else return  find(r[root], x);
        }
    };
    //带size的treap
    class Treap {
    public:
        const static int MaxN = 100000;
        int root, tsize, l[MaxN], r[MaxN], p[MaxN], nsize[MaxN];
        int key[MaxN];
    
        void maintain(const int &root) {
            int ta, tb;
            ta = l[root]==-1? 0 : nsize[l[root]];
            tb = r[root]==-1? 0 : nsize[r[root]];
            nsize[root] = ta+tb+1;
        }
        void rot_l(int &x) {    //before using this function, please ensure that the right son of x exist
            int tmp = r[x];
            r[x] = l[tmp]; maintain(x);
            l[tmp] = x; x = tmp; maintain(x);
        }
        void rot_r(int &x) {    //before using this function, please ensure that the left son of x exist
            int tmp = l[x];
            l[x] = r[tmp]; maintain(x);
            r[tmp] = x; x = tmp; maintain(x);
        }
        Treap():root(-1),tsize(-1) {}
        void insert(int &root, const int &x) {
            if(root == -1) {
                key[++tsize] = x;
                root = tsize;
                p[root] = rand();
                l[root] = r[root] = -1;
                nsize[root] = 1;
            }
            else if(x <= key[root]) {
                insert(l[root], x);
                if(p[l[root]] > p[root])  rot_r(root);
            }
            else {
                insert(r[root], x);
                if(p[r[root]] > p[root])  rot_l(root);
            }
            maintain(root);
        }
        void del(int &root, const int &x) {
            if(key[root] == x) {
                if(l[root]==-1 && r[root]==-1)  root = -1;
                else if(l[root] == -1)  root = r[root];
                else if(r[root] == -1)  root = l[root];
                else {
                    if(p[l[root]] > p[r[root]]) {
                        rot_r(root);
                        del(r[root], x);
                    }
                    else {
                        rot_l(root);
                        del(l[root], x);
                    }
                }
            }
            else if(x < key[root])  del(l[root], x);
            else del(r[root], x);
            if(root != -1)  maintain(root);
        }
        int kthElement(const int &root, int k) {
            int ta;
            ta = l[root]==-1? 0 : nsize[l[root]];
            if(ta >= k)  return  kthElement(l[root], k);
            else if(ta+1 == k)  return  key[root];
            else  return  kthElement(r[root], k-ta-1);
        }
        bool find(int &root, const int &x) {
            if(root == -1)  return  false;
            if(x == key[root])  return  true;
            else if(x < key[root])  return  find(l[root], x);
            else return  find(r[root], x);
        }
    };
  • 相关阅读:
    poj 1573 Robot Motion
    poj 1035 Spell checker
    poj 3080 Blue Jeans
    poj 3468 A Simple Problem with Integers(线段树区间更新)
    poj 3687 Labeling Balls(拓补排序)
    poj 3295 Tautology
    poj 1062 昂贵的聘礼
    hdu 1170 Balloon Comes!
    hdu 1215 七夕节
    OCJP-试题集合 | 对象的比较
  • 原文地址:https://www.cnblogs.com/aaronzlq/p/3001521.html
Copyright © 2011-2022 走看看