好久不见!
就差这个坑就补齐了!
估计高三也不会太更博客了,不知道是不是NOIP前的最后一篇?
在博客园的新博客欢迎关注!
发现自己平衡树学了跟没学一样,退役了简单学了一发……
平衡树有很多,比如AVL树,红黑树(RBTree)什么的,AVL被魔改成SBT?RBTree是系统中的平衡树。但是不常用不介绍了。
平衡树的本质是一棵二叉搜索树(Binary Search Tree,即BST),规定一个二叉树,其左儿子的值都小于它,其右儿子的值都大于它,也就是说把二叉搜索树按中序遍历即可对这些数进行排序。但是这个二叉搜索树不是唯一的。
我们可以用BST解决一些维护集合问题,比如插入一个数,查询某数排名(第几小)和查询第
可是这种操作很爆炸,当按照从小到大的顺序插入数据的时候复杂度会很大(此时BST为一条链),而且删除操作很困难。
那么就需要一些操作维护这棵BST了。
我们发现,有两个操作:左旋和右旋可以在不破坏BST性质的情况下维护这棵BST不会退化成链的形式。
下面给出一棵BST的一部分
右旋的意思即为:对于
分步的操作如下:
->
因为
那么左旋就很好理解了:对于
->
这样旋转有什么用呢?
于是就有这几种维护方式了!
1、Splay
Splay可以说是一种经典的维护方式了,通过维护
记录操作
那么如何旋转呢?
于是我们开始了大段的讨论:(其实就三种……)
1、
转一次就行了……
2、
这种情况如图:
现在
如图所示……
->
这样
3、
就是拧着的呗……
现在
如图所示……
->
于是我们可以把任意一个节点都转到根上了!
那么复杂度呢……
根据势能分析,可知
这里的势能可以理解为物理学势能,网上证明应该很多吧……这里不贴了……
Splay应用广泛,可以支持动态序列操作(如普通的平衡树),还可以支持区间变化的操作,比如区间反转,区间移动等。
如何在Splay上提取区间呢?
记需要提取
但是当
Splay还可以用在Link-Cut Tree上(即动态树),就可以维护森林中每棵树的形态了。这玩意很玄学就不补板子了……
Splay在遇到有序数据的时候还会被卡……
2、Treap
Treap是个很玄学的数据结构,它是BST和Heap的合体版本。
堆是个二叉树,其每个节点的优先级比儿子们的优先级都要小,这就是priority_queue的实现方式。
因为BST是因为一些有序数据使得其退化,然而随机数据可以认为是无序的。那么把随机数当做Heap的优先级维护Tree就可以达到平衡BST的作用。所以,我们利用左旋和右旋操作保持Heap的性质,即可达到BST的平衡。
Treap的树高期望是
Treap还有无旋维护的,是利用把树分成两块再合并的操作维护。
Treap还可以演变为替罪羊树,主要思想是暴力重构……是一种重量平衡树。
可以用Windows卡Treap(Windows下的rand范围比较小,再乘一个rand就可以防卡了……)
3、SBT
SBT是2006年在冬令营上首次出现的,可是被诸神犇喷不知道为什么……据说是换了一种方式维护AVL。
主要是用Maintain操作维护平衡,而且这个Maintain操作是均摊
在知乎上陈启峰本人已经给出了资料包,可以参考。
貌似SBT只能刷裸题+刷时间榜……
下面是喜闻乐见的板子时间……
Splay
Treap
SBT