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) 時間で実行する方法はありますか?
また、すべてのインターバル ギャップを含む 2 つ目のインターバル ツリーを作成し、そこでクエリを実行する可能性も検討しました。ノードには、そのギャップの前後にある要素に関する情報が含まれます(私は試みましたが、これを実装することにまだ成功していません)。
編集:関数 findPrevNext() は、クエリの検索に失敗した後に呼び出されます。そのため、クエリは事前に特定の間隔に収まらないことがわかっています。