Kd-Tree

A kd-tree (k-dimensional tree, Bentley 1975) is a binary space-partitioning structure for points in Rd\mathbb{R}^d that makes nearest-neighbour queries sub-linear on average. It is the default answer to “find the closest point(s)” in low-dimensional geometric data — 3D point clouds above all — and, in randomized-forest form, a practical tool for approximate matching of high-dimensional float descriptors.

Construction

Each internal node splits the point set with an axis-aligned hyperplane:

  1. Choose a splitting dimension — classically cycling through dimensions by depth (x,y,z,x,…x, y, z, x, \dots), or better, the dimension of largest variance/spread of the points in the node.
  2. Choose the splitting value — typically the median coordinate, which guarantees a balanced tree of depth O(log⁡n)O(\log n).
  3. Recurse on the two halves until nodes hold fewer than a leaf-size threshold of points.

Building costs O(nlog⁡n)O(n \log n) with median-of-medians or presorting; the tree stores each point once.

A query q\mathbf{q} first descends to the leaf containing it (O(log⁡n)O(\log n) comparisons) and takes the best point found there as the current candidate with distance rbestr_{\text{best}}. Then the search backtracks: at each node on the way up, the other subtree must be visited only if the splitting plane is closer than the current best, i.e., if

∣qk−s∣<rbest|q_k - s| < r_{\text{best}}

where qkq_k is the query’s coordinate in the node’s split dimension kk and ss the split value — geometrically, only if the hypersphere of radius rbestr_{\text{best}} around q\mathbf{q} crosses the plane. Otherwise the whole subtree is pruned. The same scheme yields k-nearest-neighbour queries (keep a heap of the best kk) and radius searches.

In low dimensions (d≲10d \lesssim 10), pruning is effective and the average query cost is O(log⁡n)O(\log n).

The curse of dimensionality

As dd grows, distances concentrate — the nearest and farthest neighbours become relatively similar in distance — and the pruning sphere intersects almost every splitting plane, so the search degenerates toward a full linear scan while paying tree-traversal overhead. As a rule of thumb, exact kd-tree search needs n≫2dn \gg 2^d to beat brute force; SIFT’s 128 dimensions are far beyond the exact-search regime. Two remedies define modern practice:

Note that kd-trees compare raw vectors under L2 — for binary descriptors under Hamming distance, LSH or HBST are the appropriate structures.

Where kd-trees appear in SLAM

Why it matters for SLAM

Nearest-neighbour search is one of the most-executed primitives in a SLAM system — inside every ICP iteration of a LiDAR or RGB-D pipeline, inside every matching stage of a feature pipeline, inside mapping operations like normal estimation and downsampling. Knowing the kd-tree’s mechanics tells you when it is the right tool (3D points: superb; 128-D descriptors: only in approximate/forest form; binary descriptors: wrong tool) and explains the design of the libraries built on top of it (FLANN’s indexes, PCL’s search module, ikd-Tree). It is also a recurring systems bottleneck: rebuild-vs-update strategies for a growing map directly shape the architecture of real-time LiDAR odometry.