我已经按照 CLRS 算法书中的概述在 Java 中实现了一个区间树(它使用红黑树作为底层结构)。在书中(据我在网上看到的),它讨论了如何找到其区间包含被查询数字的节点。
在我的情况下,如果被查询的数字不属于任何区间,我想知道“最近”节点是什么,即那些区间位于查询之前和之后的节点。我已经使用以下函数完成了这项工作。每个节点都包含区间(int low, int high),以及它们自己及其子树的最小值和最大值。
public Node[] findPrevNext(int query) {
if (tree.root.isNull())
return null;
else {
Node prev = findPrev(query, tree.root, new Node());
Node next = findNext(query, tree.root, new Node());
Node[] result = {prev, next};
return result;
}
}
private Node findPrev(int query, Node x, Node prev) {
if (x.interval.high < query && x.interval.high > prev.interval.high)
prev = x;
if (!x.left.isNull())
prev = findPrev(query, x.left, prev);
if (!x.right.isNull())
prev = findPrev(query, x.right, prev);
return prev;
}
private Node findNext(int query, Node x, Node next) {
if (x.interval.low > query && x.interval.low < next.interval.low)
next = x;
if (!x.left.isNull())
next = findNext(query, x.left, next);
if (!x.right.isNull())
next = findNext(query, x.right, next);
return next;
}
当然,问题在于函数 findPrev() 和 findNext() 都遍历整个树并且没有利用树的结构。有没有办法在 O(lgn) 时间内执行此查询?
我还考虑了创建第二个包含所有间隔间隙的间隔树的可能性,并在那里简单地进行查询。然后,节点将包含有关哪些元素在该间隙之前和之后的信息(我已经尝试过,但到目前为止还没有成功实现这一点)。
编辑:请注意,函数 findPrevNext() 在尝试查找查询失败后被调用。因此,已知查询不会事先落在任何给定的时间间隔内。