Brute-force KNN is O(nd) per query. KD-Trees partition space along axes; Ball Trees partition into hyperspheres. Both reduce average query time to O(log n) — the right choice depends on dimensionality.
K-Nearest Neighbours is conceptually simple: for a query point, find the k training points with smallest distance. The naive implementation scans every training point — O(nd) per query where n is dataset size and d is dimensionality. At a million points and 100 dimensions, that is 100 million distance computations per prediction. Specialised data structures reduce this to O(log n) on average.
A KD-Tree (k-dimensional tree) is a binary tree where each node splits the data along one axis using the median value. At depth 0 it splits on axis 0 (x), at depth 1 on axis 1 (y), cycling through all dimensions. This creates a recursive partitioning of space by axis-aligned hyperplanes. Construction is O(n log n); a single approximate nearest neighbour query is O(log n).
Search algorithm: traverse the tree like a BST to reach a leaf. Store it as the current best. Unwind upward: at each node, check if the other subtree could contain a closer point by testing whether the query circle crosses the splitting plane. If it does, explore that subtree too. This backtracking is what guarantees correctness despite the greedy descent.
A Ball Tree partitions data into nested hyperspheres (balls) rather than axis-aligned boxes. Each node stores a centroid (pivot) and a radius — the distance from the pivot to the farthest point in the node. Construction: pick two far-apart points, project all data onto their connecting vector, split at the median, recurse. Ball Trees handle high-dimensional data and data on low-dimensional manifolds much better than KD-Trees.
Triangle inequality pruning: for query q and ball with centroid c and radius r, the minimum possible distance from q to any point inside the ball is max(0, dist(q,c) - r). If this minimum already exceeds the current best distance, the entire ball is skipped. This is more effective in high dimensions where axis-aligned splits fail.
Say the answer out loud before revealing — recalling is what makes it stick. ➜ Next: BIRCH Algorithm
Why is brute-force KNN O(nd) per query?
How does a KD-Tree decide which subtree to prune during search?
Why does the KD-Tree degrade in high dimensions?
What is the key advantage of a Ball Tree over a KD-Tree?