算法导论第十四章:数据结构的扩张

    在应用工程中,需要在现有的数据结构上有所创新,但很少需要创造出全新的数据结构。通常情况下,只要向标准的数据结构中增加一些信息即可。可以对数据结构编入新的造作,以支持所需的应用。但是,数据结构的扩张并不总是轻而易举的,附加的信息需要能为该数据结构的常规操作所更新和维护。这一章讨论通过扩展红黑树构造的数据结构。

动态顺序统计

   第9章介绍了顺序统计的概念,在一个无序的集合中,任意的顺序统计量都可以在O(n)时间内找到。在这一节里,将介绍如何修改红黑树的结构,使得任意的顺序统计量都可以在O(lgn)时间内确定。

一棵顺序统计量树T通过简单地在红黑树的每个结点存入附加信息而成。在一个结点x内,除了原有的域,还包括size[x],这个域包含以结点x为根的子树的节点数:
Size[x] = size[left[x]] + size[right[x]] +1

 

检索具有给点排序的元素算法如下,只要调用OS-SELECT(root[T],i):
OS-SELECT(x, i)
1     r = size[left[x]]+1
2     if i = = r
3     then return r
4     Else if i<r
5     Then return OS-SELECT(left[x],i)
6     Else return OS-SELECT(right[x],i-r)

 

确定一个元素的秩:
OS-RANK(T, x)
1     r = size[left[x]]+1
2     y = x
3    while y != root[T]
4    do if y==right[p[y]]
5    then r = r+size[left[p[y]]]+1
6    y = p[y]
7    return r

 

对子树规模的维护:
给点每个结点的size域后,OS-SLELECT和OS-RANK能迅速地计算出所需的顺序统计信息。然而,除非能够用红黑树上基本的修改操作对这些size域加以有效的维护,否则,就达不到期望的目的。
插入结点:在寻找插入位置的过程中,所经路径上的结点size域都需加1
旋转:如果插入结点后,需要旋转某些结点,可以验证,可以在常数时间内更新相关结点的size域。

如何扩张数据结构

对一种数据结构进行扩张,一般分为四个步骤
1 选择基础数据结构
2 确定选取什么信息作为关键字,选取什么信息作为附加字段,这些选择取决于设计目的
3 验证可在数据结构的常规操作中来维护新加的信息,一般来说如果某个信息只直接依赖于其子节点的信息的话,维护某个节点该信息只需要常数时间。
4 设计新的操作

以上节的顺序统计树为例,我们不是在结点中存储顺序统计量,而是存储子树的节点数,这是因为前者很难维护。而有了后者我们也可以在较快时间lgn内得出顺序统计量。

区间树:

一个闭区间是一个实数的有序对[t1,t2],其中t1<=t2。区间可以很方便第表示占用连续时间的事件。我们可以把一个区间[t1,t2]表示成一个对象i,其各个域为low[i]=t1,high[i]=t2。两个区间i和j满足一下三种关系之一:
1 重叠
2 i在j左边,即high[i]<low[j]
3 i在j右边,即high[j]<low[i]

我们需要维护一个动态区间集合,并能迅速找到与某个已知区间重叠的集合元素。


先按上节所述的方法来构造区间树:
1 基础数据结构
    选择红黑树,其中每个结点x包含区间域int[x],关键字为区间的低端点low[int[x]]。这样对树进行中序遍历就可以按低端点的次序输出区间。
2 附加信息
    每个结点除了区间信息之外,还包含一个值max[x],即以x为根的子树所有区间的端点的最大值。
3 对信息的维护
    验证对max域的维护能在常规的插入、删除操作中完成:
    max[x] = max( high[int[x]], max[left[x]], max[right[x]]),这样更新max域只需要常数时间。
4 新的操作
INTERVAL-SEARCH(T, i)
1.    x  root[T]
2.    while x!=nil[T] and i dose not overlap int[x]
3.    do if left[x] != nil[T] and max[left[x]]>=low[i]
4.    then x left[x]
5.    else x right[x]
6.    return x


上述算法的关键点在于第3-5行的选择,在结点x与i不重叠前提下,如果x存在左树,且左子树的最大端点大于i的低点,则往左子树搜寻:这个选择是正确的,应为如果在这种条件下左子树中不存在和i重叠的结点,右子树种也不会存在。因为max[left[x]]>=low[i],左子树中必然存在某结点y,high[y]>=low[i],如果y与i不重叠,则有low[y]>high[i],则x右子树的所有结点的低端都大于high[i]。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值