博客
关于我
【用梨泰院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/

    你可能感兴趣的文章
    nginx添加模块与https支持
    查看>>
    Nginx用户认证
    查看>>
    Nginx的Rewrite正则表达式,匹配非某单词
    查看>>
    Nginx的使用总结(一)
    查看>>
    Nginx的可视化神器nginx-gui的下载配置和使用
    查看>>
    Nginx的是什么?干什么用的?
    查看>>
    Nginx访问控制_登陆权限的控制(http_auth_basic_module)
    查看>>
    nginx负载均衡器处理session共享的几种方法(转)
    查看>>
    nginx负载均衡的5种策略(转载)
    查看>>
    nginx负载均衡的五种算法
    查看>>
    Nginx运维与实战(二)-Https配置
    查看>>
    Nginx配置ssl实现https
    查看>>
    Nginx配置TCP代理指南
    查看>>
    Nginx配置——不记录指定文件类型日志
    查看>>
    Nginx配置代理解决本地html进行ajax请求接口跨域问题
    查看>>
    Nginx配置参数中文说明
    查看>>
    Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
    查看>>
    Nginx配置实例-负载均衡实例:平均访问多台服务器
    查看>>
    Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
    查看>>
    NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
    查看>>