Range queries & Range trees

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/BigFatSheep/article/details/80678470

Range queries

给一些空间中的数据点,查询(query)在一定查询范围(query region)中的累积信息(aggregate information)

可以计算点点数量,列出点,最高优先级点,平均数,方差等

Decomposable Range Queries

A range query is decomposable if there is some binary operation ⊗
such that:
1. ⊗ is associative, commutative, and has an identity operand
2. If Q is a region and we split Q into two disjoint regions X
and Y :
query(Q) = query(X) ⊗ query(Y )
如果操作时可结合可交换的,并且在一个大范围上的查询可以分解为小范围上的,那么这个range query is decomposable。
比如说计数,求和,union,minimum等。
但求平均数是not decomposable的,因为不知道两部分的数量,不能直接两部分之间求平均。要计算sum和count后除出来。

1维动态可分解范围查询

数据有实数key(data不一定),在闭区间[L,R]上。数据可以插入或者删除。

使用平衡二叉搜索树来保存结果。那么排序结果就是平衡二产搜索树的中序遍历(左中右)的结果。每一个节点记录他以及他的后代的节点数目,根结点就保存了整棵树的节点数。

The value of augment(x) for a non-null node is defined by:
augment(x) = value(x) ⊗ augment(x.left) ⊗
augment(x.right)

For a null node:
augment(null) = the identity operand for ⊗

当我们插入或者删除节点之后,重新计数augment(x)

循转后,
1. augment(x) = augment(y)
2. Use the formula to recomputed augment(y)

查询

在区间[L, R]上进行查询
1. 找到区间中的最高节点v
2. 找到之后,分别搜索v的左右子树
3. 在v的左子树:
如果一个节点x的key < L,那么x的左子树肯定在区间外了,可以忽略;x的右子树可能在区间内。
如果节点x的key >= L,那么x的右子树一定在区间内,我们不用搜索它,只需把augment(x.right) 合并进查询值中即可;x的左子树可能在区间中,去查它。
4. 在v的右子树:
如果一个节点x的key > R,那么x的右子树肯定在区间外了,可以忽略;x的左子树可能在区间内。
如果节点x的key <= L,那么x的左子树一定在区间内,我们不用搜索它,只需把augment(x.left) 合并进查询值中即可;x的右子树可能在区间中,去查它。

超了就往里找补,这个点不算;
没超就向外作,这个点和里面的都算。
先向左后向右。

伪代码

def query(T,L,R):
if T.key < L:
    return query(T.right,L,R)
if T.key > R:
    return query(T.left,L,R)
if R == +∞:
    return query(T.left,L,R) ⊗ value(T) ⊗ augment(T.right)
if L == -∞:
    return augment(T.left) ⊗ value(T) ⊗ query(T.right,L,R)
return query(T.left,L,+∞) ⊗ value(T) ⊗ query(T.right,−∞,R)

时间复杂度分析

If
1. Query answers require O(1) memory and
2. ⊗ takes O(1) time
Then
All operations in 1-dimensional dynamic range queries (insert, delete, query) can be performed in O(log n) time per operation.

如果我们想列出在范围内的所有keys,之前的分析不能用了。因为操作变成了列表合并

report的伪代码:

def report(T,L,R):
if T.key < L:
return report(T.right,L,R)
if T.key > R:
return report(T.left,L,R)
if R == +∞:
return report(T.left,L,R) ⊗ key(T) ⊗ list(T.right)
if L == -∞:
return list(T.left) ⊗ key(T) ⊗ report(T.right,L,R)
return report(T.left,L,+∞) ⊗ key(T) ⊗ report(T.right,−∞,R)

猜你喜欢

转载自blog.csdn.net/BigFatSheep/article/details/80678470