Splay

来源:互联网 发布:大数据的弱点 编辑:程序博客网 时间:2024/04/24 20:33

思想

Splay_tree,伸展树,顾名思义就是用伸展来进行平衡的平衡树。伸展操作是把一个节点伸展到根上的操作,当然不是简单的旋转到根,而是:(绿色节点是x,蓝色节点为p,红色节点为g)
这里写图片描述
①当p是根节点时,只需要一次正常的旋转即可。
这里写图片描述
②当p不是根节点,x,p,g“三点共线”时,先旋转p,然后旋转x。
这里写图片描述
③当p不是根节点,x,p,g“三点不共线”时,旋转两次x。

每次插入,询问,删除,合并,分裂后,都需要伸展。可以证明得到每次操作均摊复杂度是log2(n),但是单次操作复杂度可能较高(比如在好多次伸展后变成了链,那么单次复杂度就变成了O(n),但链会被接下来的伸展打破,下次操作可能比log2(n)还小)。

插入,询问,删除都是常规的(只不过之后要伸展),这里就讲讲合并和分裂。
合并:
这里写图片描述
①当S1中的所有元素小于S2(比如S1和S2是刚刚分裂出来的)时,只需要把S1最大的点伸展到根,然后连边即可。
②当S1和S2大小任意时,启发式合并,把小的往大的身上挪。
分裂:(以k为界限,左边小于或等于k,右边大于或等于k)
这里写图片描述
只需要把k伸展到根,然后根据情况断开连接即可。

ps:学过Treap以后,不难写出代码,这里就不给出了(我才不会告诉你们是我写模板没debug成功T_T),只给出一个伸展操作:

void Splay(P_node &id,int k) //请确保k存在{    int d1=id->cmp(k);    if (d1!=-1)    {        P_node p=id->son[d1];        int d2=p->cmp(k);        if (d2!=-1)        {            Splay(p->son[d2],k); //先递归处理下面            if (d1==d2) Rotate(id,d1^1),Rotate(id,d1^1); else //三点共线            Rotate(id->son[d1],d2^1),Rotate(id,d1^1); //三点不共线        } else Rotate(id,d1^1); //旋转一次    }   }
1 0
原创粉丝点击