Treap=Tree+Heap! 各种BST大PK(模板)

来源:互联网 发布:手机arp防火墙软件 编辑:程序博客网 时间:2024/05/20 15:39

        刚开学时间确实比较多,于是便继续补寒假的坑。

        看了标题应该就很明确了,此篇就是讲又一种平衡树Treap的。可以说Treap这个名字取的真的很好,如题Treap=Tree+Heap!

        这个数据结构的特点在于非常的简洁易懂,当然了,前提是你学好了其他的平衡树。它的代码量是公认比较少的,不敢说最少……下面说说它的实现方式。我们知道,一棵普通的BST由于存储方式固定,所以不免会出现一些数据使得时间复杂度退化,比如说出现了链。但是如果我们随机的给每个数字添加一个优先级,并且按照优先级次序对BST进行调整,即使是普通的BST也能够做到理论上的O(NlogN)。所以,Treap就利用了这个方法,对于每一个数值,随机产生一个优先级fix(这里按照优先级大的在上),然后你会发现,对于原数值,它是一棵BST,对于fix他又是一个大根堆,所以说是Treap=Tree+Heap。

        具体实现的话就只有一处特别,就是insert操作,每次插入新数字,随机产生fix。然后每次在BST中找到位置后,再维护堆的性质,如果fix大于父亲,那么通过旋转使得fix大的变为父亲,如此往复。具体看代码:

inline void insert(int &i,int x){if (!i){i=++sz;tree[i].num=x;tree[i].fix=rand();//随机生成fixtree[i].cnt=tree[i].size=1;return;}tree[i].size++;if (x==tree[i].num){tree[i].cnt++;return;}if (x<tree[i].num){insert(tree[i].l,x);if (tree[tree[i].l].fix>tree[i].fix) Right_Rotate(i);//如果fix大于父亲,就旋转} else{insert(tree[i].r,x);if (tree[tree[i].r].fix>tree[i].fix) Left_Rotate(i);//如果fix大于父亲,就旋转}}

         其他操作,与普通平衡树大同小异,我就不贴上来了,然后至于模板题,我也懒得放上来了。

         下面上重头戏,各种BST大PK。今年寒假主攻了我之前所薄弱的高级数据结构,主要学习了Splay、Link Cut Tree、Partition Tree、Treap、Sized Balanced Tree、Chairman Tree……然后最重要的三种BST都学完了,当然要进行一个对比了,Splay VS SBT VS Treap(我们以模板题BZOJ3224为例):

                1、速度方面:        毋庸置疑的SBT拥有绝对的优势(毕竟人家高度的平衡),然后Treap紧随其后(随机算法不稳定),Splay遗憾的排在了最后,我觉得是我自己Splay                                        写残了的缘故……

                2、编程复杂度:    这个当然是本文的主角Treap占优势啦,人家短小精悍,Splay和SBT就不相上下,还是得说,估计是我Splay写残了……

                3、适用范围:        终于轮到Splay排第一啦,由于Splay的灵活性,它可以被运用到很多地方(Link Cut Tree),然后SBT和Treap就差不多了。

        下面给出我的运行结果,自上而下分别是Splay、Treap和SBT。显示的Code_Length比较长是因为我的头文件还有读入输出优化。

        好了,关于BST的基本介绍就到这了,估计以后也不会想去学AVL和RBT了,毕竟有这三个貌似已经足够了。

0 0
原创粉丝点击