BST总结

Posted hlw1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BST总结相关的知识,希望对你有一定的参考价值。

BST 是 Treap 的基础。

这位大佬写的不错

只写一点基本操作方便自己理解。

性质:左儿子 < 自己 < 右儿子

上图

技术图片

插入

根据性质,比当前结点小就插入左子树,大就插入右子树,相等直接令当前结点的 cnt++ 即可。

void insert(int o, int k) {//在当前结点 o 插入 k 值
    tr[o].sz++;
    if (tr[o].val == k) {
        tr[o].cnt++;
        return;
    }
    if (v < tr[o].val) {
        if (tr[o].ls != 0) insert(tr[o].ls, k);
        else {
            tot++;
            tr[tot].val = k, tr[tot].sz = tr[tot].cnt = 1;
            tr[o].ls = tot;
        }
    }
    else {
        if (tr[o].rs != 0) insert(tr[o].rs, k);
        else {
            tot++;
            tr[tot].val = k, tr[tot].sz = tr[tot].cnt = 1;
            tr[o].rs = tot;
        }
    }

删除

直接找到该数字所在的结点,令 cnt-- 就好了。

代码就不写了

因为上面那位大佬没写

前驱

一个数的前驱是指小于这个数的最大的数。

如果当前结点的值大于这个数,直接递归进左子树中找,小于的话就递归进右子树中找。

int pre(int o, int k, int ans) {
    if (tr[o].val >= k) {
        if (!tr[o].ls) return ans;
        else return pre(tr[o].ls, k, ans);
    }
    else {
        if (!tr[o].rs) {
            if (tr[o].val < k) return tr[o].val;//必须小于这个数
            else return ans;
        }
        else if (tr[o].cnt) return pre(tr[o].rs, k, tr[o].val);//注意此时当前结点的值一定小于 ans ,要更新 ans
        else return pre(tr[o].rs, k, ans);
    }
}

后继

和前驱的方法是一样的。

int suf(int o, int k, int ans) {
    if (tr[o].val <= k) {
        if (!tr[o].rs) return ans;
        else return suf(tr[o].rs, k, ans);
    }
    else {
        if (!tr[o].ls) {
            if (tr[o].val > k) return tr[o].val;
            else return ans;
        }
        else if (tr[o].cnt) return suf(tr[o].ls, k, tr[o].val);
        else return suf(tr[o].ls, k, ans);
    }
}

排名

当前结点的排名为它的左子树大小加上自己的 cnt ,如果小于要找的排名,就递归进右子树,并更新排名,否则先查找是否是当前结点,不是再去左子树。

int GetRank(int o, int rk) {
    if (!o) return INF;
    if (tr[tr[o].ls].sz >= rk) return GetRank(tr[o].ls, rk);
    else if (tr[tr[o].ls].sz + tr[o].cnt >= rk) return tr[o].val;
    return GetRank(tr[o].rs, rk - tr[tr[o].ls].sz - tr[o].cnt);
}

找值

如果当前结点的值小于查询的值,就在右子树找,同时排名要加上当前结点左子树的大小和当前结点的 cnt 值,否则直接递归进左子树找。

int GetVal(int o, int k) {
    if (!o) return 0;
    if (tr[o].val == k) return tr[tr[o].ls].sz + 1;
    else if (tr[o].val > k) return GetVal(tr[o].ls, k);
    return GetVal(tr[o].rs, k) + tr[tr[o].ls].sz + tr[o].cnt;
}

以上是关于BST总结的主要内容,如果未能解决你的问题,请参考以下文章

树和二叉树总结—BST二叉排序树

python常用代码片段总结

BootStrap有用代码片段(持续总结)

BootStrap实用代码片段(持续总结)

回归 | js实用代码片段的封装与总结(持续更新中...)

查看发票组代码后的总结和有感