Splay Tree 伸展树

写在前面:我是巨菜……代码巨丑~请各种大牛不要鄙视……

Splay也就是传说中的伸展树~以前很想学,但是因为旋转比较晕,所以一直没学~这回因为决定学了,所以就看了看,写了写。经历了3个小时的摸索……终于写出来了……

首先说我用的题,是一道专门测平衡树的题:

 给出N(N<=1000000)个操作,然后有N行,每行两个数,ch和k
ch=1表示插入一个值为k的数
ch=2表示查询第k小的数
ch=3表示删除值为k的数(k一定存在)
我之前的平衡树速度测试和学习都用的这道题(P.s.据说是陈启峰神牛的数据)。Splay是所以神奇就是因为它的灵活,我还是按照我的习惯来说说这个东西。想看的更具体一点呢,可以去看看sqybi神牛的经典Splay教程《The Magical Splay》(地址:http://www.oibh.org/bbs/viewthread.php?tid=23645&highlight=splay

首先,平衡树的重要操作肯定少不了旋转,Splay的旋转就是个很悲剧的东西。因为splay的精髓在于把一个点旋转到任意一个位置,所以要记录每个点的父亲。但是一旦旋转中出现了父亲,很多东西都很IMBA~

还是一样,两种旋转ZIG和ZAG。ZIG(x)表示当x为它父亲的左儿子时,将x旋转到父亲的位置上的操作,ZAG则反之。(这个东西要认真写,差一点都会出大问题。)

然后就是伸展树的精髓,就是Splay(x,y)过程,就是将x旋转到y的儿子的位置,当y=0的时候旋转到根。这样就一共有6种情况,写写还可以。

然后就是怎么用它来维护树的平衡,说白了就是每次搞完了之后就将操作的那个点旋转到根去就好。所有操作中比较神奇的应该说是删除操作,首先找到您要删除的节点转到根上,然后找到比它大的最小的数和比它小的最大的数。(P.s.说白了就是找前驱和后继),这个时候要看这两个指针是否为空,如果是空,那么直接把root改下就好。反之,如果左右都有,那么将前驱转到根上,然后将后继转到前驱的右儿子上,细心的人这时候就发现,根的右儿子的左儿子只有一个元素,就是我们要删掉的那个元素。这样就结了,干掉这个点就好……

实测情况:

P.s.skyprophet那个是我以前的treap,cqf那个是陈启峰神牛的SBT,splay就是我这会写的东西了。~~

【代码】:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值