T - The type for the start and end point of the intervalpublic class TreeNode<T extends Comparable<? super T>> extends Object implements Iterable<Interval<T>>
IntervalTree.
Since the Interval Tree is practically a binary search tree, every node is identified by a unique key - the center (called middlepoint) of the first interval that triggers the creation of this node. The key is immutable and can't be changed during the lifespan of this node. It can however move up or down in the tree as a result of balancing rotations, similarly to a normal balanced search tree. Unlike a traditional binary search tree, every node in the interval tree can store multiple intervals. The invariant is, that each node stores only intervals that contain its middlepoint.
There are several invariants that the TreeNode needs to keep. First,
the subtrees rooted in each node are always kept balanced. Second, each node
must contain at least one interval, otherwise the node must be removed from
the tree to keep it as small as possible. Balancing is done by traditional
binary search tree rotations.
Given an interval that needs to be found, inserted or removed from the tree, an augmented binary search algorithm is performed in the following fashion. For each visited node, check if the middlepoint of this node is contained in the query interval. If so, then this node is the position where the query interval must be stored. Otherwise, visit the left child, if the interval is entirely to the left of the middlepoint, or visit the right child otherwise.
Since intervals may contain middlepoints from multiple nodes in the tree,
there are multiple valid locations where an interval may be stored based
on the above augmented binary search algorithm. However, to ensure the
optimal time complexity of the add,
remove and
contains operations, we define the base
position of an interval (or base) as the node closest to root within the set of
nodes, where the interval may be stored. To be able to guarantee the
correctness of the algorithm, this invariant must be preserved after each
tree operation. This is especially important, when tree rotations are
performed. Whenever a node is promoted closer to the root as a result of a
rotation, the promoted node must assimilate all intervals from the node demoted
by the rotation. This ensures that whenever the binary search algorithm encounters
a node, which is a valid location for a given interval, this node will be the base
of the interval.
Since each node can store multiple intervals, we need an efficient way
to perform intersecting queries (given a query in the form of a point or
an interval, find all intervals intersecting the query). The TreeNode
can't simply keep an ArrayList of all intervals stored in it, because
it will have to linearly check each interval in the List. This can
degrade the performance of the tree, especially in cases where a single
node contains all intervals. Intervals have to be stored in an ordered
way. Each node keeps its intervals in two TreeSets at the same
time - one containing the intervals by their start points in ascending order
and the other by the end points in descending order. Whenever we have to provide
a set of all intervals contained within this node, that intersect a query point,
we check if the query is left or right of the middlepoint of the node.
If it is left, we iterate through the TreeSet ordered by the start points
until we reach an interval completely to the right of the query. Analogously,
if the query is to the right of the middlepoint, we iterate through the set
ordered by the end points until we reach an interval that's completely to
the left of the query. This allows us to only iterate through these intervals,
that we will actually return as a result of the query.
| Modifier and Type | Field and Description |
|---|---|
protected NavigableSet<Interval<T>> |
decreasing
A set containing all
Intervals stored in this node, ordered by their
starting points. |
protected int |
height
The height of the node.
|
protected NavigableSet<Interval<T>> |
increasing
A set containing all
Intervals stored in this node, ordered by their
end points. |
protected TreeNode<T> |
left
A pointer to the left child of the current node.
|
protected T |
midpoint
The midpoint of the initial interval added to the node.
|
protected TreeNode<T> |
right
A pointer to the right child of the current node.
|
| Constructor and Description |
|---|
TreeNode(Interval<T> interval)
Instantiates a new node in an
IntervalTree. |
| Modifier and Type | Method and Description |
|---|---|
static <T extends Comparable<? super T>> |
addInterval(IntervalTree<T> tree,
TreeNode<T> root,
Interval<T> interval)
Adds a new interval to the subtree rooted at a
TreeNode. |
int |
height()
Returns the height of the subtree, rooted at the current node.
|
com.lodborg.intervaltree.TreeNode.TreeNodeIterator |
iterator()
An iterator over all intervals stored in subtree rooted at the current node.
|
static <T extends Comparable<? super T>> |
query(TreeNode<T> root,
T point,
Set<Interval<T>> res)
A helper function for the
IntervalTree.query(Comparable) method. |
static <T extends Comparable<? super T>> |
removeInterval(IntervalTree<T> tree,
TreeNode<T> root,
Interval<T> interval)
A helper function for the
IntervalTree.remove(Interval) method. |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitforEach, spliteratorprotected NavigableSet<Interval<T extends Comparable<? super T>>> decreasing
Intervals stored in this node, ordered by their
starting points.Interval.sweepLeftToRightprotected NavigableSet<Interval<T extends Comparable<? super T>>> increasing
Intervals stored in this node, ordered by their
end points.Interval.sweepRightToLeftprotected TreeNode<T extends Comparable<? super T>> left
left.midpoint.compareTo(this.midpoint) < 0 must evaluate to true.protected TreeNode<T extends Comparable<? super T>> right
right.midpoint.compareTo(this.midpoint) > 0 must evaluate to true.protected final T extends Comparable<? super T> midpoint
protected int height
public TreeNode(Interval<T> interval)
IntervalTree.interval - The initial interval stored in the node. The middlepoint of
the node will be set based on this interval.public static <T extends Comparable<? super T>> TreeNode<T> addInterval(IntervalTree<T> tree, TreeNode<T> root, Interval<T> interval)
TreeNode.T - The type of the start and end points of the interval.tree - The IntervalTree containing the subtree. Used primarily for
housekeeping, such as adjusting the size of the tree, if needed.root - The root of the subtree, to which we are adding a new interval.interval - The Interval that we are adding.public int height()
public static <T extends Comparable<? super T>> Set<Interval<T>> query(TreeNode<T> root, T point, Set<Interval<T>> res)
IntervalTree.query(Comparable) method.
It searches recursively for all intervals stored in the subtree rooted at
the current node, that intersect a target point.T - The type of the start and end points of the intervals, as well as
the query point.root - The root of the currently traversed subtree. May be null.point - The query point.res - The set used to store all intervals to be returned.public static <T extends Comparable<? super T>> TreeNode<T> removeInterval(IntervalTree<T> tree, TreeNode<T> root, Interval<T> interval)
IntervalTree.remove(Interval) method.
It searches recursively for the base node of a target interval and
removes the interval from the base node, if it is stored there. This is
a more efficient way to remove an interval from the tree, since it
doesn't iterate through all intervals, but performs a binary search in
O(logn).T - The type of the start and end points of the intervals, as well as
the query point.tree - The IntervalTree containing the subtree. Used primarily for
housekeeping, such as adjusting the size of the tree, if needed.root - The root of the currently traversed subtree. May be null.interval - The target interval to be removed.null if the interval
was the last one stored at the subtree.public com.lodborg.intervaltree.TreeNode.TreeNodeIterator iterator()
Copyright © 2016. All rights reserved.