本章通过扩张红黑树构造出两种数据结构:动态顺序统计和区间树。
1、动态顺序统计:查找倒数第i小的数据 复杂度为 lg(n)
为什么是扩张红黑树而不是搜索二叉树或者二叉树?
相对于搜索二叉树,红黑树的平衡性更好,高度在lg(n) 。这样查找时的复杂度就是 lg(n)而不是n。在第9章顺序统计量的时候列出了运行时间期望为线性和最坏运行时间为线性的
算法(http://www.cnblogs.com/NeilZhang/p/5650226.html) 。
struct的结点的结构: 与一般的红黑树相比,增加了 size ,对于任意一个结点 p.size = p.left->size + p.right->size + 1
struct RBTreeNode{ int key; int color; struct RBTreeNode *parent; struct RBTreeNode *left; struct RBTreeNode *right; int size; };
对于检索具有给定排序的元素:逐层查找
OS_SELECT(x,i) r = size[left[x]]+1; //先计算x的处于的位置 if i = r //x正好是第i小的关键字 then return x; else if i < r //x比第i关键字大,则在其左子树查找 then return OS_SELECT(left[x],i) else return OS_SELECT(right[x],i-r) //x比第i关键字小,则在其右子树查找
确定一个元素的秩(知道元素的值大小,确定它的 排序位数)
OS-RANK(T,x) r=x.left.size +1 y=x while y!=T.root if y==y.p.right r=r+y.p.left.size + 1 y=y.preturn r
树的维护
主要是针对 插入 和删除 操作的维护,在红黑树的插入删除的基础之上还要 在插入和删除之后 维护 size的大小,(需要从这个分支一直到root结点)复杂度为 lg(n)
对于红黑树的旋转操作也要在其中添加有关size的比变化。
2、如何扩张数据结构
对一种数据结构的扩张过程分为四个步骤:
1)选择基础数据结构
2)确定要在基础数据结构中添加哪些信息
3)验证可用基础数据结构上的基本修改操作来维护这些新添加的信息
4)设计新的操作
书中给出了对红黑树进行扩张的定理,并给出了证明,这个看的时候有些难度,暂时跳过了。大概意思就是说当红黑树被选作基础数据结构时,某些类型的附加信息总是可以用插入和删除来进行有效地维护。
3、区间树
这小结讲的是扩张红黑树以支持由区间构成的动态集合上的操作。区间可以很方便的表示各占用一段连续时间的一些事情。区间树是一种动态集合进行维护的红黑树,该集合中的每个元素x都包含在一个区间int[x]。区间树支持下列操作:
INTERVAL_INSERT(T,x):将包含区间域int的元素x插入到区间树T中
INTERVAL_DELETE(T,X):从区间树T中删除元素x
INTERVAL_SEARCH(T,i):返回一个指向区间树T中元素x的指针,使int[x]与i重叠,若集合中无此元素存在,则返回nil[T]。
修改红黑树得到的区间树如下图所示:
从图可以看出,对区间树以每个节点的左端点值进行中序变量即可得到有序的序列。有了区间树的结果就很容易实现其相关操作。