概念
伸展树是一种二叉查找树,具有二叉查找树的性质.而与二叉查找树相比,伸展树具有的特点是:当某个节点被访问时,伸展树会通过旋转使该节点成为树根。
伸展树操作的时间复杂度较低的原因是:把访问频率高的结点放在根节点附近
伸展树的旋转算法
伸展树的重点在与旋转算法,有三种旋转类型:
- zig
- zig-zig
- zig-zag
设有结点x,p是x的父母结点,g是p的父母结点
zig:当p是根节点,旋转类型为zig
zig-zig:当p不是根节点,且x和p均为右孩子结点,或左孩子结点
这种情况下,p先向右旋转,然后x向右旋转即可将x结点旋转至根结点
zig-zag:当p不是根节点,且x,p分别为右孩子结点和左孩子结点,或者左孩子结点和右孩子结点
在这种情况下,x先向左旋转,然后向右旋转
基本操作
Find
先调用普通二叉搜索树的Find函数找到对应结点
对找到结点调用splay函数,使该结点成为根节点
返回根节点
伪代码实现
STFind(x, R)
N <--- Find(x, R)
Splay(N)
return N
Insert
像普通二叉搜索一样插入元素x
调用splay函数,使刚插入的元素x成为根节点
伪代码实现
STInsert(x, R)
Insert(x, R)
STFind(x, R)
Delete
调用Next(x)找到大于x的最小结点
调用splay(Next(x))将找到的结点旋转至根节点
调用splay(x)将要删除的结点旋转至根节点
调用普通二叉搜索树的删除函数delete删除根节点
伪代码实现
STDelete(x)
splay(Next(x))
splay(x)
Delete(x)
split
调用是splay(x)函数,将x旋转至根节点,此时根节点的左子树的元素均小于x,右子树均大于元素x
右子树为R2,剩下部分为R1
伪代码实现
STSplit(x)
N <--- Find(x, R)
splay(N)
R2 <--- right subtree of R
R1 <--- the rest of the tree
return (R1, R2)
Merge
调用Find(max, S)找出小树S中的最大元素x
调用splay(x),此时小树S中没有了右子树
把大树T当做S的右子树即可
STMerge(S, T)
x = Find(max, S)
splay(x)
S.Right <--- T
return S