MIT:算法导论——11.扩充的数据结构、动态有序统计和区间树
2014-06-19 11:20
721 查看
算法导论第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。
如果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:设计新操作。
分支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重叠的区间。
========================================================================
【图示化补充】
【顺序统计树】下面给出一个修改后的红黑树的例子,如下图所示:
【区间树】修改红黑树得到的区间树如下图所示:
从图可以看出,对区间树以每个节点的左端点值进行中序变量即可得到有序的序列。
为应对新的应用需求,经常是通过存储额外信息的方法来扩张一种标准的数据结构,
然后对这种数据结构,编写新的操作来支持所需要的应用。
一、动态顺序统计
一种支持一般动态集合上,顺序统计操作的数据结构。
通过这种数据结构,可以快速地找到一个集合中的第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重叠的区间。
========================================================================
【图示化补充】
【顺序统计树】下面给出一个修改后的红黑树的例子,如下图所示:
【区间树】修改红黑树得到的区间树如下图所示:
从图可以看出,对区间树以每个节点的左端点值进行中序变量即可得到有序的序列。
相关文章推荐
- 【算法导论】第十一课 扩充的数据结构、动态有序统计和区间树
- 算法导论--动态顺序统计与区间树
- 数据结构之五(数据结构的扩充、动态统计、区间树)
- 算法导论 第四部分——基本数据结构——第15章:动态规划:背包问题
- 算法系列笔记5(扩展数据结构-动态顺序统计和区间树)
- 数据结构的扩张(动态有序统计和区间树)笔记
- MIT:算法导论——7.1.基本数据结构_栈、队列、链表、有根树
- 数据结构 2-11设顺序表va中的数据元素递增有序。试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性。
- 算法导论16.1-3 区间图着色(interval-graph coloring)问题(贪心算法)
- 区间图着色问题(算法导论课后题目16.1.3)
- 算法导论——第七章——基本数据结构
- MIT 6.046J / 18.410J 2001秋季课程:算法导论(Introduction to Algorithms, Fall 2001)第一课
- 算法导论学习笔记(15)——用于不相交集合的数据结构
- 微软等数据结构+算法面试100题(11)--压缩字符串
- 基本数据结构(算法导论)与python
- 动态连续区间和查询,Binary Index Tree 算法
- 算法导论-5.基本数据结构
- 算法导论第十四章习题14.1-4递归方式统计元素的秩
- 【算法导论】第15章动态规划
- 《算法导论》第14章 数据结构的扩张 (1)动态顺序统计