关于平衡树的一些总结

Posted wfj_2048

tags:

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

平衡树是个大专题啊qwq。。最近也学了一些很有用的平衡树,写个总结吧。。

 

一.splay

学的第一个平衡树,复习一下。。

splay是一个功能很强大的二叉搜索树。其实讲道理splay并不算平衡树吧,因为它并没有任何关于树高的限制。splay的原理就是,每次插入或查询一个结点,就把它旋转到根结点,这样与搜索引擎的原理类似,查询次数较多的结点就能更靠近根。splay并不能保证每次操作严格复杂度都是O(logn),但是每次操作的均摊复杂度确实可以是O(log)。。然而我也不知道为什么。。不过splay好像有可能会被卡来着。。但是splay在序列上的操作可以说几乎完美,因为它可以任意旋转。splay的编程复杂度也是很小的。

splay的核心在于splay操作,即调用splay(x,f),就是把x旋转到f的儿子上(特别地,如果把x旋到根那么f=0)。splay的旋转分为3种——zig,zig-zig,zig-zag。zig操作,就是当x的父亲已经是f的儿子时,直接旋转x。zig-zig,当x与x的父亲位于同一侧时(就是说,x是x的父亲的左儿子,x的父亲是x的父亲的父亲的左儿子,反之也成立)。先旋转x的父亲,再旋转x。zig-zag,当x与x的父亲位于不同侧时,直接旋转两次x。这里的旋转,就是指,如果x是它父亲的左儿子,那么就把他右旋,否则左旋。感觉上个图会更容易理解些。。

技术分享

 

然后就是上代码了。。

 1 il void rotate(RG int x){
 2     RG int y=fa[x],z=fa[y],k=ch[y][0]==x;
 3     ch[z][ch[z][1]==y]=x,fa[x]=z;
 4     ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y;
 5     ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
 6 }
 7 
 8 il void splay(RG int x,RG int goal){
 9     RG int top=0; st[++top]=x;
10     for (RG int i=x;fa[i]!=goal;i=fa[i]) st[++top]=fa[i];
11     for (RG int i=top;i;--i) if (lazy[st[i]]) pushdown(st[i]);
12     while (fa[x]!=goal){
13     RG int y=fa[x],z=fa[y];
14     if (fa[y]!=goal){
15         ((ch[z][0]==y)^(ch[y][0]==x)) ? rotate(x) : rotate(y);
16     }
17     rotate(x);
18     }
19     if (!goal) rt=x; return;
20 }

splay还是很好写的吧,还能对一个序列进行分裂和合并这种神奇的操作qwq。。

 

二.替罪羊树

替罪羊树也是一种很好写的平衡树qwq。。替罪羊树的核心思想就是重构。即当一棵子树的平衡被破坏,那么就把这棵树拍平,也就是树高为O(logn)的完美二叉树形态。这样看似复杂度很高,实则不然。可以证明,替罪羊树每次重构的复杂度都是均摊O(logn)的。反正我也不会证明,证明还要用物理学知识。。

---------------------------------------------------------------------------------------------------------------------------------------------------

具体是这样操作的:我们设定一个参数α,满足α[0.5,1)。(其实如果你设定α为0.5那就会T飞~)

α高度平衡:树高hlog1an

α大小平衡:对于一个结点p满足max(sizelp,sizerp)αsizep

如果每个结点均满足α大小平衡,假设最深的点为dd,那么有1nαdepd

那么depdlogα1n=log1αndepd≤logα1n=log1αn,即满足α高度平衡。

插入和普通BST类似,只需要判断插入操作是否导致了这一条链上结点的大小平衡被破坏,如果有的话将深度最浅的点所在子树暴力重建。重建最简单的方法就是对这棵子树中序遍历后分治建树。通过势能分析可以证明每一次插入的均摊复杂度为logn

查询和普通BST并无区别。

删除操作比较巧妙。对于一次删除,我们并不马上移除这个点,而是直接这个点上打上删除标记,查询时跳过该点。重构时可以顺便删除打了删除标记的点。当被删除结点的个数超过总结点数的(1?α)倍时可以选择重构整棵树进行结构优化,并且显然这部分重构的复杂度不会超过O(nlogn)。

---------------------------------------------------------------------------------------------------------------------------------------------------

——以上内容蒯自xLightGod学长(http://blog.xlightgod.com/%E3%80%90bzoj3224%E3%80%91%E6%99%AE%E9%80%9A%E5%B9%B3%E8%A1%A1%E6%A0%91/)

 


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

关于树的判定(满二叉树完全二叉树平衡二叉树相似二叉树等价二叉树)

平衡二叉树的旋转类型及代码实现

红黑树的原理+实现

关于二叉查找树的一些事儿(bst详解)

关于AVL树的思考

关于平衡二叉树的核心算法--旋转