MIT:算法导论——11.扩充的数据结构、动态有序统计和区间树

算法导论第14章 【数据结构的扩张】
    为应对新的应用需求,经常是通过存储额外信息的方法来扩张一种标准的数据结构,
然后对这种数据结构,编写新的操作来支持所需要的应用。


一、动态顺序统计
一种支持一般动态集合上,顺序统计操作的数据结构。
通过这种数据结构,可以快速地找到一个集合中的第i小的数,(select)
或给出一个指定元素在集合的全序中的位置。(rank)
【已知】对于一个无序的集合,能够在O(n)的时间内确定任何的顺序统计量。
rank(x):获得x在数组中的位置,遍历数组并统计比x.key小的元素数即可。
select(i):利用random-partion()函数,二分地去定位即可。
【目标】修改红黑树,使得在O(lgn)时间内确定任何的顺序统计量。
【顺序统计树】在每个结点上存储附加信息的一棵红黑树。
除了基本结点属性x.key、x.color、x.p、x.left、x.right之外,还附加x.size属性。
设哨兵T.nil的x.size为0,则有等式: x.size = x.left.size + x.right.size + 1。

OS-SELECT( x, i ) // 过程返回一个指针,指向以x为根的子树中包含第i小关键字的结点
	r = x.left.size + 1
	if i == r
		return x
	else if i < r
		return OS-SELECT( x.left, i )
	else
		return OS-SELECT( x.right, i - r )
OS-RANK( T, x ) // 过程返回T中序遍历对象的线性序中x的位置
	r = x.left.size + 1
	y = x
	while y != T.root
		if y == y.p.right
			r += y.p.left.size + 1
		y = y.p
	return r
【OS-RANK解释】
如果y是y.p的左孩子,y.p和y.p的右子树中所有结点都不会先于x,r保持不变。
如果y是y.p的右孩子,y.p和y.p的左子树中所有结点都先于x,r要加上y.p.left.size + 1。
【对子树规模的维护】
LEFT-ROTATE( T, x )的代码,要添加下面两行:
y.size = x.size // y = x.right
x.size = x.left.size + x.right.size + 1
RIGHT-ROTATE( T, x )的代码,要添加下面两行:
y.size = x.size
x.size = x.left.size + x.right.size + 1
维护size时间复杂度:O(1)。所以插入、删除,包括维护size属性,都只需要O(lgn)时间。


二、如何扩张数据结构(Ex. OS-trees)
(1)选择一种基础数据结构。(red-black tree)
(2)确定基础数据结构中要维护的附加信息。(subtree size,直接记录秩也可以,不过速度太慢了)
(3)检验基础数据结构上的基本修改操作能否维护附加信息。(Insert、Delete/Rotate是否可以维持子树大小的信息)

(4)设计一些新操作。(怎么使用这些信息:OS-Select、OS-Rank)


【实际使用时】上面可能更像一个checklist,而设计时可以先设计一个些新操作(4),再去验证附加信息维护等。

【2+2】2组数据 + 2组操作:基础操作+附加操作 : 基本操作+新添操作



三、区间树
一个区间[t1, t2]表示成一个对象i,其中属性i.low = t1为低端点, i.high = t2为高端点。
【区间i与i'重叠(overlap)】
如果i与i'的交集非空,即如果i'.low <= i.high and i.low <= i'.high。
任何两个区间i与i'满足【区间三分定律】,即下面三条性质之一成立:
(1)i和i'重叠。
(2)i在i'的左边,即i.high < i'.low

(3)i在i'的右边,即i.low > i'.high


Example Interval Trees : Maintain a set of intervals.

eg : time intervals.




【区间树】一种对动态集合进行维护的红黑树,其中每个元素x都包含一个区间x.int。
区间树支持下列操作:
(1)INTERVAL-INSERT( T, x ):将包含区间属性的int的元素x插入到树T中。
(2)INTERVAL-DELETE( T, x ):从T删除x。
(3)INTERVAL-SEARCH( T, i ):返回一个指向T中元素x的指针,使x.int与i重叠。不存在返回T.nil。
【扩张数据结构】
步骤1:基础数据结构
一棵红黑树,每个结点x包含一个区间属性x.int,且x的关键字为区间int的低端点x.int.low。
所以该数据结构的中序遍历,就是按低端点的次序排列的各区间。
步骤2:附加信息
包含一个值x.max,它是以x为根的子树中,所有区间的端点的最大值。
步骤3:对信息维护
通过x.int和x子结点的max,有 x.max = max( x.int.right, x.left.max, x.right.max )。
故一次旋转后,更新max属性只要O(1)的时间;所以插入和删除的运行时间为O(lgn)。
步骤4:设计新操作。
INTERVAL-SEARCH( T, i )
	x = T.root
	while x != T.nil and i does not overlap x.int
		if x.left != T.nil and x.left.max >= i.low // i'.low <= i.high 
			x = x.left
		else
			x = x.right
	return x
【解释】
分支if执行时,如果在以x.left为根的子树中,没有与i重叠的区间,
则树的其他部分也不会包含与i重叠的区间。
分析:有x.left.max >= i.low,根据max属性定义,在x的左子树中必定存在某区间i',满足:
i'.high = x.left.max >= i.low,
如果i与i'不重叠,则i.high < i'.low <= i''.low,其中i''为右子树中任意区间,
所以右子树也不包含与i重叠的区间。

========================================================================

【图示化补充】

【顺序统计树】下面给出一个修改后的红黑树的例子,如下图所示:

【区间树】修改红黑树得到的区间树如下图所示:

从图可以看出,对区间树以每个节点的左端点值进行中序变量即可得到有序的序列。




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值