简介
平衡树,顾名思义,平衡的搜索二叉树。
常见的平衡树都能将树的深度保持在 lg n \lg_n lgn 的级别内,防止退化成链。
一些平衡树可以通过旋转、分裂、合并等操作完成更加高级的、二叉搜索树做不到的操作。
二叉搜索树
在讲平衡树之前,先介绍这种二叉树。
1、性质&特点
首先,规定:对于节点 x x x , x x x 左子树内任一点权值< x x x 权值< x x x 右子树内任一点权值。
这一条性质也被称为 bst ( b i n a r y s e a r c h t r e e ) \text{bst}(binary\ search\ tree) bst(binary search tree) 性质。
由此性质可以容易地发现对于一棵二叉搜索树,如果没有插入或删除,节点的中序遍历是固定的。
当然,是在没有重复元素的前提下。至于重复元素在下面。
2、支持操作
先规定以下变量、数组:
-
tot,rt:节点数量以及根的编号。 -
v[i]:节点 i i i 的权值。 -
fa[i]:节点 i i i 的父亲编号。 -
chi[i][2]:节点 i i i 的左/右儿子。 -
cnt[i]:节点 i i i 的权值存在数量(如数列1 1 2 3,如果v[3]=1,那么cnt[3]=2)。 -
sz[i]:节点 i i i 的子树中权值数量。形式化地写,sz[i]=sz[chi[i][0]]+sz[chi[i][1]]+cnt[i]。
特别地,空节点编号为0。
插入一个元素:根据 bst \text{bst} bst 性质,从根开始,向左右两侧跳。直到空位或者已有该元素大小的节点。
查询元素 x x x 的前驱:先根据 bst \text{bst} bst 性质,找到元素 x x x 所在的节点。如果 x x x 有左子树,那么前驱是它左子树内最靠右的节点;如果 x x x 没有左子树但有父亲,那前驱就是它的深度最深的、 x x x 位于右子树内的祖先。
查询元素 x x x 的后继:类似前驱。
查询元素 x x x 的排名:
- 如果 x x x 小于当前权值,向左子树。
- 答案加上左子树大小,如果 x x x 等于当前权值,将答案加1并返回;否则加上当前点的 cnt \text{cnt} cnt 并向右子树。
查询排名为 k k k 的数值:
- 如果 k k k 小于左子树大小,向左子树。
- 将 k k k 减去左子树大小。如果 k ≤ 0 k\le0 k≤0 ,返回当前权值;否则向右子树。
3、死因
不难发现,如果我一直插入 1 , 2 , 3...... n 1,2,3......n 1,2,3......n ,这棵树会因此而退化成一条链。
如果离线处理,可以考虑将插入的数排序后再递归建树:
Function : d g ( l , r ) &

本文介绍了平衡树的概念,强调了其防止二叉搜索树退化为链的重要性。详细阐述了二叉搜索树的性质、插入与查询操作,并讨论了平衡树中的Splay树。Splay树通过旋转操作保持平衡,同时提供了插入、查找、删除等高效操作。此外,还展示了如何在Splay树中进行区间操作,如区间翻转。最后,给出了Splay树的C++实现及例题解析。
最低0.47元/天 解锁文章
1462

被折叠的 条评论
为什么被折叠?



