Range searching and kd-trees
Separate balanced search depth from the geometry of a multidimensional query.
On this page
The question for today
What you’ll understand
- Build a balanced cyclic-coordinate kd-tree and identify canonical subtrees.
- State the fixed-dimensional orthogonal range-reporting bound with output cost.
- Explain why nearest-neighbor or high-dimensional queries need separate analysis.
An orthogonal range query asks which stored points lie in an axis-aligned box. A kd-tree recursively partitions points by coordinate cuts and lets a query accept or reject whole subtrees. The tree can have logarithmic height while one query still visits many branches: geometric boundary crossings, not height alone, determine its cost. We analyze median-balanced trees with cyclic coordinate choices in a fixed dimension at least two. For the clean proof, assume distinct coordinate values on each axis, with cuts between adjacent values and an explicit closed-query boundary policy.
Balance the points and retain their enclosing regions
At a node, split the points near the median of the current axis and cycle to the next axis at the following level. Store one point per leaf, and associate each node with its spatial cell and optionally a tighter bounding box of its points. Balanced partitioning gives logarithmic height and linear total nodes. Presorted coordinate lists with linear-time partitioning, or appropriate linear-time selection at each level, give sorting-scale construction; independently sorting every recursive subset would need a different cost analysis.
To answer a box query, reject a node whose enclosing region is disjoint from the query, accept its entire canonical subset if the region is contained, and otherwise recurse. A leaf still requires an exact membership test. Counting can use a cached subtree count when accepting a whole subset; reporting must write every returned point. Tighter bounding boxes can improve pruning but cannot invalidate the conservative cell tests. Equal coordinates and cut-boundary coincidences require a tie-aware partition and query convention rather than assuming that all geometric regions are disjoint closed boxes.
Bound the cells cut by a query boundary
In two dimensions, consider a vertical query boundary passing through a cyclic balanced tree. At a vertical split it enters at most one relevant child; at a horizontal split it can enter both. Across two levels, the number of candidate branches doubles while their point counts fall by about a factor of four. This produces a square-root boundary-crossing bound. The rectangle has only four sides, so their total contribution remains square-root scale; the returned points contribute the separate output term.
In fixed higher dimension, the analogous cyclic argument gives the exponent shown above. The constants depend on dimension, and the exponent approaches one as dimension grows. Consequently a kd-tree is not a dimension-independent logarithmic range structure. Different split rules, including longest-side or arbitrary adaptive choices, may have different theoretical guarantees even when they work well in practice. Balance by itself is insufficient for this geometric analysis; the axis schedule is part of the theorem.
Nearest neighbors ask a different pruning question
For nearest-neighbor search, one can compare the current best distance with a lower bound on distance to a node's box. Rejecting a box whose lower bound is too large is correct, but does not guarantee logarithmic worst-case work. Adversarial configurations can make an exact search inspect a linear number of points, even in a fixed low dimension. Distributional assumptions or an approximation tolerance can support other guarantees, but they must be named and proved separately.
Coordinate transformations also matter. An invertible shear preserves point incidence and convexity, yet an axis-aligned query becomes a parallelogram. Its axis-aligned enclosing box can be much larger than the transformed query, weakening pruning. A range bound for orthogonal boxes cannot simply be relabeled as the same theorem for arbitrary rotated or sheared shapes. The practical data structure should be chosen around the query family, output type, dimension, and acceptable approximation, rather than around a familiar tree name alone.
Work it through
Accept an entire half-tree
Build the first two levels for points using an x-cut at , then median y-cuts. Report the points in closed query box using tight subtree boxes.
The root separates the four points with x at most four from the other four. The left y-values are , giving cut ; the right y-values are , giving cut .
The left tight bounding box is , entirely inside the query. The right tight box is , disjoint from it. Thus the query can accept the left canonical subset and reject the right without descending for membership tests.
The answer is , with output size four. Continuing balanced splits gives eight leaves, seven internal nodes, and height three in edges. Writing the four answers still takes four output operations.
Subtree acceptance saves geometric decisions but cannot remove reporting cost. This particular easy query does not establish a logarithmic bound for every rectangle.
The living notebook
Explore the model
Interactive lab · matrix
A shear loosens an axis-aligned enclosing box
Pause/Reset and set BOTH controls to , : the unit square and its axis-aligned bounding box both have area . For a fresh comparison Pause/Reset and set BOTH to , . Predict a parallelogram of area inside bounding box , of area . Changes retain the paused clock; matrix readouts always describe the selected final map.
- Area scale · det A
- 1.4
- Singular values · σmax, σmin
- 1.597, 0.876
- Condition number · κ₂(A)
- 1.823
The selected matrix is A = [[a,b],[0,1]]. Playback interpolates geometry between the identity and A; readouts always describe A. Its determinant is a and its singular values come from AᵀA. Positive a makes every supported matrix invertible. This two-dimensional family is not a general eigensolver or a learned network. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forThe enclosing box doubles its area while the actual transformed query does not. The matrix instrument illustrates axis alignment; it does not construct or query a kd-tree.
Pause & reason
Check your understanding
Your turn
Try it yourself
Using the same eight points, list all points in the closed box . Identify points included exactly on its boundary, and explain why an implementation cannot replace closed membership by an unspecified strict comparison.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Check both coordinates for each point; a coordinate equal to either endpoint is included.
Compare with the solution
The answer is . The first lies on the left boundary, the third on the bottom, and the last on the top and right boundaries. Points fail at least one coordinate test. Strict comparisons would incorrectly drop three valid outputs. Tree-cell ownership can be half-open internally, but the public closed-box query must still implement its declared inclusive membership rule.
Keep the idea
Take it with you
- Canonical subtrees let queries accept or reject many points together.
- The standard bound uses fixed dimension, cyclic median splits, and orthogonal boxes.
- Logarithmic height does not imply logarithmic worst-case range or nearest-neighbor search.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.