平衡树
说到平衡树,很多人的第一印象就是: 难学(知识点真多) 难懂(特别是“旋转”和证明) 难调(我的某个教练刚学平衡树的时候调了七个小时) 下面我们就来从0开始讲平衡树。 (注:网上大多数人说到“平衡树”默认指的是“Splay”而不是其他算法) 定义 其实平衡树(Balance Tree,简称BT)不算一种算法,而是一种统称。 平衡树顾名思义就是非常平衡的树。 比如说这棵树就非常不平衡: 而这棵树就比较平衡: 如果说的更形式化,平衡就意味着,对于每个点,其所有子树的大小差都不超过 $1$。 具体而言,对于每个点 $x$,如果我们把其所有儿子 $to$ 的子树大小都列出来,那么这个数组内最大值和最小值差不超过 $1$。 而且,大多数平衡树都是二叉树,这一点是为了方便操作和设计算法。 种类 听完上面的定义,你就知道了,平衡树就是一类树状数据结构的统称。 下面就来列举一下这类数据结构都有哪些,以及这些数据结构的简介。 二叉搜索树(Binary Search Tree,简称BST) 大多数平衡树的前置算法,这也就意味着,大多数的平衡树都是基于BST并进行优化、扩展后得到的算法。 而BST也是线段树(Segment Tree,部分情况下会简称为ST)进行扩展后的算法。 具体而言,权值线段树和BST都可以维护有序集合,但有时候只能用BST解决。 BST其实就是把权值“当做”节点编号(讲的时候一般就这么讲,但写的时候不能这么写,是把权值存入该节点的结构体内)。 然后对于每个点,它都有最多 $2$ 个儿子,左儿子权值 $<$ 当前点权值 $<$ 右儿子权值。 这样就可以方便查找。 优点:代码好写,容易讲明白 缺点:解决题型少,需要写定期重构(又被称作“替罪羊树思想”),复杂度高 Treap(名字不是一个单词,而是两个单词Tree和Heap的结合) 这个算法给每个节点都添加了一个“优先级”,并让“优先级”满足小/大根堆的性质。 并且,这里还通过“旋转”操作(最头疼的地方来了)让树尽量平衡,这样会让树高稳定在 $O(\log n)$ 级别。 (不过注意,在最坏情况下,复杂度会达到 $O(n)$,所以 $O(\log n)$ 只是期望) 这样,复杂度就降下来了。 优点:复杂度低,比较容易理解,解决题型多,且容易被识别出 缺点:比较难写,细节较多,复杂度难证明 Splay(本意为“张开”但这里不是这个意思) 这个算法对上面的“旋转”操作又做了一遍扩展,让其能够解决子串翻转问题。 而且,由于它也会让整棵树尽量平衡,所以树高还是会稳定在 $O(\log n)$ 级别。 ...