这一篇写了伸展树的学习就想告一段落了!毕竟也纠结这么久了!本来觉得自己已经理解得差不多了,就不想总结了,但想到“好记性不如烂笔头",就还是都写下来吧!

    在《运用伸展树解决数列维护问题》里已经对“怎么在伸展树中表示任意区间"这一问题说得很清楚了,只是没有说到具体的操作实现。

    首先,也是最重要的,我们认为伸展树中序遍历即是我们维护的序列!什么意思呢?比如有数据在数组中这样存放:a[5]={5,4,3,1,2};那么存入伸展树后,再中序遍历的结果应该还是:{5,4,3,1,2}。即下标从小到大,而不是里面的值从小到大!这是与SBT树最大的不同!

    伸展树的区间提取操作:
为了能更好的了解,我把树弄得复杂一点:

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_动态区间维护

 

从根结点开始,中序遍历整个树:能保证从小到大排列!(图中的数字指下标)

如果我们要提取区间[4,8]怎么做呢?

第一步:把4的前驱,也就是3旋转到根结点:先是5 (右旋(zig)),5旋转到根结点,然后再旋转3右旋(zig,3旋转到根结点(也就是所提到的一字旋转)

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_提取区间_02

第二步:把8的后继9旋转到根结点的右孩子位置:这里比较复杂,

1、原图:

 

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_Splay Tree_03

1、  操作一:把9旋转到10的位置:zag一次

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_Splay Tree_04

操作二:把9旋转到8的位置:zag

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_动态区间维护_05

操作三:把9旋转到6的位置:

 

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_Splay Tree_06

操作四:把9旋转到5的位置:

伸展树的学习(六):伸展树的区间操作(区间翻转,旋转,增加一个数,求最小值)_数列维护_07

 

这样我们就提出出区间[4,8]了,区间在哪里呢?根结点右孩子的左子树!

 

区间提取出来后,可做的操作就自由了!比如:把整个区间删除,区间的的所有元素加上某个数,区间翻转,区间旋转!

如果需要插入一段区间怎么做呢?

比如:在序列:{1 , 2 ,3 ,4 ,5 }4的后面插入{678},整个区间变成:{1 , 2 , 3 , 4 , 6 , 7 , 8 , 5}

这也相当容易:把4旋转到根结点:5旋转到根结点的右孩子!那么:根结点右孩子的左孩子必定为空: 先把需要插入的区间组织成一棵伸展树,然后把新树的根结点接到5的左孩子就可以了!