在X插入时,展开使得X成为新的根。
查找X时,也要对X或者是因为没找到而路径上最后一个节点进行展开。
初步想法是沿着根往下进行一次遍历,以及而后从底向上的一次遍历。这样太麻烦了啊。
所以本文介绍自顶向下的伸展树:在初始访问路径上就进行一次次的旋转。
我们设X为中间树的根,L存放树T中小于X中的节点,但不存放X的子树的节点,R同理。初始化时X为T的根,L和R为空树
我们设展开函数为Splay(int Item,Position X),也就是说如果Item在X中,那么Item要变成新的根;不在的话,路径上最后一个点要变成新的根。
分为以下三种情况进行旋转(其实一共六种,其余三种对称即可)
①: 单旋转->
②zig-zig:先对x-y进行AVL里的单旋转,再对y-z进行一次①:
所以就是说进行一次单旋转,就能和①结合了
③:zig-zag:
这里我们用简易版zig-zag,这样就能和①相结合了
然后看如何恢复为一棵树
----》》》
根据这个函数,我总结了一下应该是这么个思路:
首先创建一个NullNode,它的值为item;具体为什么下面再解释
①如果Item<X:
①如果Item比X的左节点小,那就执行一次单旋转,X=X->left(解释:如果X左节点不存在,那么Item就和X左节点一样大了)
②之后如果X的左节点不存在,那么就结束了。
③存在的话,就可以执行三种旋转中的第一种了。
②如果Item>X:
对称一下
③如果Item==X;
就把左中右三个树合并起来
插入:进行一次Splay(Item,X),在根据Item<>=X,进行插入更改即可。
疑问:只用到O(1)空间,摊还时间为O(logN)
时间: 2024-12-25 14:27:54