An interval tree is a data structure for efficiently searching intervals. Surprise! An interval can be a continuous line segment, a time frame, etc. It is generally augmented with a secondary structure in each interval node to allow for windowing queries. A good example is quickly finding a rectangular region in a GIS application. I couldn’t find a really straightforward explanation of the algorithm. The Wikipedia entry, while correct, was not well-explained from an implementation point of view. Most of this information comes from the great book Computational Geometry by Berg et. al.
There are different types of interval trees. The CLRS Introduction to Algorithms book uses a red-black tree as the starting point and outlines construction and querying for intervals. The approach outlined below is a centered interval tree, which uses a binary search tree where each subtree is also a centered interval tree. The value of each subtree is the median (left or right) endpoint of the intervals in the subtree.
An interval, at it’s barest, has a left and right endpoint. That’s it. Let’s look at how we’d construct an interval tree given a set of intervals. I’ll use pseudo-Java since I think it’s the friendliest to read.
CenteredIntervalTree constructIntervalTree(Set<Interval> intervals) {
if intervals.isEmpty()
return leaf;
Compute xMid = Median of interval endpoints
Compute iMid = the set of all intervals
where the left endpoint is <= xMid
and the right endpoint is >= xMid
Compute iMidLeft = a copy of the set iMid sorted by left endpoint
Compute iMidRight = a copy of the set iMid sorted by right endpoint
Store xMid, iMidLeft, and iMidRight at the current node.
Compute iLeft = a set of all intervals where the RIGHT endpoint is < xMid
Compute iRight = a set of all intervals where the LEFT endpoint is > xMid
leftSubTree = constructIntervalTree(iLeft)
rightSubTree = constructIntervalTree(iRight)
return currentTree;
}
The construction algorithms creates a roughly-balanced search tree by taking the median of the (right) endpoints and setting that as the root of the current tree. The data stored at each node is the set of intervals that contain that endpoint. To see how this construction algorithm works, assume we have the following set of intervals: {(1, 10), (17, 29), (31, 38), (30, 40), (15, 24)}. The resulting interval tree will appear as in the image below. The running time for the construction algorithm is O(n log n). For the proof, see Lemma 10.3 in Computation Geometry.

So how do we query this? The answer should be obvious when looking at the image. The only trick is when you wish to query for all intervals intersecting another interval.
To query for a given point (say, to find all intervals containing the value 35 in the example), the following algorithm can be used:
Set<Interval> queryIntervalTree(tree, value) {
if (tree does not have children)
return currentSet;
if (value < xMid) {
for (Interval interval : iMidLeft) {
if (interval.contains(value))
currentSet.add(interval);
else
break; //sorted so that nothing past this will contain value
}
currentSet.addAll(queryIntervalTree(tree.leftSubTree, value));
} else {
/* Repeat iteration from above but with iMidRight instead of iMidLeft;
currentSet.addAll(queryIntervalTree(tree.rightSubTree, value));
}
}
The query time is a very fast O(log n + k), where k is the number of intervals that are stored at a node. But what if we wanted to search for an interval? This is fairly easy, but can be difficult to express: We want to start at the left endpoint, and grab all intervals until we reach the right endpoint intersection. From an implementation perspective, it can be hard to do this correctly. You can’t just call queryIntervalTree for the left and right endpoint values, you might miss intervals that are completely enclosed by the passed in interval. So, when implementing, it might be smart to replace some of the recursion with iteration, or at least keep track of the parent nodes for a centered interval tree. This will make walking the tree much easier.