博客
关于我
【用梨泰院class中的财阀世家带你洞悉替罪羊树】Scapegoat Tree原理,模板,例题
阅读量:294 次
发布时间:2019-03-03

本文共 2974 字,大约阅读时间需要 9 分钟。

重新理解替罪羊树

前言

我最近在学习数据结构时,逐渐对平衡树的概念产生了浓厚兴趣。通过对比和实践,我逐渐理解了替罪羊树的工作原理。这让我联想到韩剧中的财阀世家,复杂的权力斗争和权力更迭让我对替罪羊树的“拍扁重构”机制有了更深入的理解。

替罪羊树的概念

替罪羊树是一种基于“拍扁重构”的二叉平衡树,通过打乱子树的结构来维护平衡性。与旋转平衡树相比,替罪羊树更注重通过稳固的“亲情”来维持树的平衡。

核心原理

替罪羊树的平衡机制依赖于一个叫做“平衡因子”的概念。这个因子用于判断树的子树是否需要重构。具体来说,当左或右子树的节点数占比超过平衡因子的限制时,整个子树就会被拍扁重构。

平衡因子的选择

平衡因子的取值范围通常在0.5到1之间。常见的选择是0.7左右。这一参数值的选择需要权衡插入和查询的效率。较大的α值会减少重构次数,提高插入效率,但可能导致查询效率下降。

替罪羊树的优点与缺点

优点

  • 代码简洁:替罪羊树的代码逻辑相对简单,易于调试。
  • 性能较好:在大多数操作下,替罪羊树的性能表现优于一些旋转平衡树。
  • 易于理解:其“拍扁重构”机制直观地类似于对家族权力结构的调整。
  • 缺点

  • 区间操作受限:替罪羊树不支持区间操作,这在某些应用场景下是个限制。
  • 重构频率高:在某些负载下,频繁的重构操作可能带来性能瓶颈。
  • 替罪羊树的实现

    数据结构定义

    struct Scapegoat {    bool exist;    int son[2], val, alive, total;};int idx1, idx2, flag, root, Size;int cur[MAXN], memory[MAXN];

    重构函数

    void flat(int rt) {    if (!rt) return;    flat(t[rt].son[0]);    if (t[rt].exist) cur[++idx1] = rt;    else memory[++idx2] = rt;    flat(t[rt].son[1]);}void build(int l, int r, int &rt) {    int mid = (l + r) >> 1;    rt = cur[mid];    if (l == r) {        t[rt].son[0] = t[rt].son[1] = 0;        t[rt].alive = t[rt].total = 1;        return;    }    if (l < mid) build(l, mid - 1, t[rt].son[0]);    else t[rt].son[0] = 0;    build(mid + 1, r, t[rt].son[1]);    t[rt].total = t[t[rt].son[0]].total + t[t[rt].son[1]].total + 1;    t[rt].alive = t[t[rt].son[0]].alive + t[t[rt].son[1]].alive + 1;}void rebuild(int &rt) {    idx1 = 0;    flat(rt);    if (idx1) build(1, idx1, rt);    else rt = 0;}

    插入函数

    void insert(int &rt, int val) {    if (!rt) {        rt = memory[idx2--];        t[rt].val = val;        t[rt].exist = t[rt].alive = t[rt].total = 1;        t[rt].son[0] = t[rt].son[1] = 0;        return;    }    t[rt].alive++;    t[rt].total++;    if (val <= t[rt].val) insert(t[rt].son[0], val);    else insert(t[rt].son[1], val);    if (Bad(rt)) rebuild(rt);}

    删除操作

    void Delete_rnk(int &rt, int rnk) {    if (t[rt].exist && t[t[rt].son[0]].alive + 1 == rnk) {        t[rt].exist = 0;        t[rt].alive--;        return;    }    t[rt].alive--;    if (rnk <= t[t[rt].son[0]].alive + t[rt].exist)        Delete_rnk(t[rt].son[0], rnk);    else        Delete_rnk(t[rt].son[1], rnk - t[t[rt].son[0]].alive - t[rt].exist);}void Delete_val(int val) {    Delete_rnk(root, FindRank(val));    if ((double)t[root].total * alpha > t[root].alive)        rebuild(root);}

    查找功能

    int FindRank(int k) {    int rt = root, ans = 1;    while (rt) {        if (k <= t[rt].val) rt = t[rt].son[0];        else {            ans += t[t[rt].son[0]].alive + t[rt].exist;            rt = t[rt].son[1];        }    }    return ans;}int FindKth(int k) {    int rt = root;    while (rt) {        if (t[rt].exist && t[t[rt].son[0]].alive + 1 == k)            return t[rt].val;        else if (k <= t[t[rt].son[0]].alive)            rt = t[rt].son[0];        else {            k -= (t[t[rt].son[0]].alive + t[rt].exist);            rt = t[rt].son[1];        }    }    return -1;}

    总结

    替罪羊树以其独特的“拍扁重构”机制,为平衡树提供了一种直观的理解方式。通过类比现实中的财阀世家权力斗争,我们可以更直观地感受到替罪羊树的工作原理。虽然其在某些场景下存在局限性,但其代码简洁、逻辑清晰,使其成为学习平衡树的一种不错的选择。

    转载地址:http://pxil.baihongyu.com/

    你可能感兴趣的文章
    ORM框架 和 面向对象编程
    查看>>
    OS X Yosemite中VMware Fusion实验环境的虚拟机文件位置备忘
    查看>>
    os.environ 没有设置环境变量
    查看>>
    os.path.join、dirname、splitext、split、makedirs、getcwd、listdir、sep等的用法
    查看>>
    os.removexattr 的 Python 文档——‘*‘(星号)参数是什么意思?
    查看>>
    os.system 在 Python 中不起作用
    查看>>
    OS2ATC2017:阿里研究员林昊畅谈操作系统创新与挑战
    查看>>
    OSCACHE介绍
    查看>>
    SQL--合计函数(Aggregate functions):avg,count,first,last,max,min,sum
    查看>>
    OSChina 周五乱弹 ——吹牛扯淡的耽误你们学习进步了
    查看>>
    SQL--mysql索引
    查看>>
    OSChina 周四乱弹 ——程序员为啥要买苹果手机啊?
    查看>>
    OSChina 周日乱弹 —— 2014 年各种奇葩评论集合
    查看>>
    OSChina 技术周刊第十期,每周技术抢先看!
    查看>>
    OSError: no library called “cairo-2“ was foundno library called “cairo“ was foundno library called
    查看>>
    OSError: [WinError 193] %1 不是有效的 Win32 应用程序。
    查看>>
    osgearth介绍
    查看>>
    OSGi与Maven、Eclipse PlugIn的区别
    查看>>
    Osgi环境配置
    查看>>
    OSG——选取和拖拽
    查看>>