本文共 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/