Treap树

Treap是真的简单。

为了打破类似单调数列插入BST,

使树退化为链表的情况,

将数据打乱成随机出现的,是个好办法,

然而并不是什么时候都适用。

 

树上节点的出现顺序是不可修改的,

而Treap则为每个节点新增加一个随机变量,

将矛盾转移到这个随机变量上,

使得对节点进行比较的时候,具有随机性,

从而使得插入,删除等操作的复杂度期望为O(logn)。

Treap性质:

1.左右子树的优先级小于父亲。

 

插入:

与BST同样的,左小右大跑子树,插入节点,没什么特殊的。

回溯时进行修正。

删除:

平衡二叉树删除节点总是这样:

1.找到待删除的节点。

2.如果它没有儿子,或是只有一个儿子,可以就地删除,后续接上。

3.如果它有两个儿子,则继续递归,找它的前驱,用前驱替换待删除节点,删除前驱节点。

回溯时进行修正。

修正:

插入时,引入新节点,需要修正。

删除时,从叶子替换了一个节点过来,需要修正。

步骤:

1.判断当前节点优先值小于父亲优先值,如果它是左儿子则右旋,否则左旋。

没了。

#include <iostream>
#include <cstdio>
#include <climits>
#include <cstdlib>
#include <fstream>
using namespace std;
struct Tree {
    int num, num2, value, rand;
    Tree *lChild, *rChild;
}*T, *NIL;
void lTurn(Tree *&th) {
    Tree *p = th;
    th = th->rChild;
    p->rChild = th->lChild;
    th->lChild = p;
}
void rTurn(Tree *&th) {
    Tree *p = th;
    th = th->lChild;
    p->lChild = th->rChild;
    th->rChild = p;
}
void updateNode(Tree *th) {
    if (th != NIL) {
        th->num2 = th->lChild->num2 + th->rChild->num2 + th->num;
    }
}
void balance(Tree *th, Tree *&par) {
    if (th != NIL && par != NIL) {
        if (th->rand > par->rand) {
            if (th == par->lChild) {
                rTurn(par);
            } else {
                lTurn(par);
            }
        }
        updateNode(par->lChild);
        updateNode(par->rChild);
    }
    updateNode(par);
}
void insertNode(Tree *&th, int value, Tree *&par = NIL) {
    if (th == NIL) {
        th = new Tree;
        th->num = th->num2 = 1;
        th->value = value;
        th->lChild = th->rChild = NIL;
        th->rand = rand();
    } else if (th->value == value) {
        ++th->num;
        ++th->num2;
    } else {
        insertNode(value < th->value? th->lChild: th->rChild, value, th);
    }
    balance(th, par);
}
void deleteNode(Tree *&th, int value, Tree *&par = NIL, Tree *q = NIL) {
    if (q == NIL) {
        if (th->value == value) {
            if (th->num > 1) {
                --th->num;
                --th->num2;
            } else if (th->lChild == NIL || th->rChild == NIL) {
                Tree *p = th;
                th = th->lChild != NIL? th->lChild: th->rChild;
                delete p;
            } else {
                deleteNode(th->lChild, value, th, th);
            }
        } else {
            deleteNode(value < th->value? th->lChild: th->rChild, value, th);
        }
    } else {
        if (th == NIL) {
            Tree *p = par;
            q->num = par->num;
            q->rand = par->rand;
            q->value = par->value;
            par = par->lChild;
            delete p;
        } else {
            deleteNode(th->rChild, value, th, q);
        }
    }
    balance(th, par);
}
int getRank(Tree *th, int value) {
    if (th == NIL) {
        return 0;
    } else if (th->value < value){
        return th->lChild->num2 + th->num + getRank(th->rChild, value);
    } else {
        return getRank(th->lChild, value);
    }
}
int getSa(Tree *th, int sa) {
    if (th == NIL) {
        return -1;
    } else {
        int lower_sa = th->lChild->num2 + 1;
        int upper_sa = lower_sa + th->num;
        if (sa < lower_sa) {
            return getSa(th->lChild, sa);
        } else if (sa < upper_sa) {
            return th->value;
        } else {
            return getSa(th->rChild, sa - upper_sa + 1);
        }
    }
}
int getPre(Tree *th, int value) {
    if (th == NIL) {
        return -1 << 30;
    } else if (th->value < value) {
        int x = getPre(th->rChild, value);
        return (x != -1 << 30)? x: th->value;
    } else {
        return getPre(th->lChild, value);
    }
}
int getSuf(Tree *th, int value) {
    if (th == NIL) {
        return 1 << 30;
    } else if (th->value > value) {
        int x = getSuf(th->lChild, value);
        return (x != 1 << 30)? x: th->value;
    } else {
        return getSuf(th->rChild, value);
    }
}
int main() {
    srand(time(0));
    NIL = new Tree;
    NIL->num = NIL->num2 = 0;
    NIL->rand = INT_MIN;
    T = NIL;
    int n, opt, x;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &opt, &x);
        switch(opt) {
        case 1:insertNode(T, x);break;
        case 2:deleteNode(T, x);break;
        case 3:printf("%d\n", getRank(T, x) + 1);break;
        case 4:printf("%d\n", getSa(T, x));break;
        case 5:printf("%d\n", getPre(T, x));break;
        case 6:printf("%d\n", getSuf(T, x));break;
        }
    }
    return 0;
}

题目:落谷普通平衡树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值