A K-D Tree (K-Dimensional Tree) is a space-partitioning data structure designed for organizing points in a K-dimensional space. It’s particularly efficient for nearest neighbor searches, range queries, and other spatial operations. Each node in the tree represents a point in K-dimensional space and a hyperplane that splits the space into two regions.
Description:- Root Node: The root node contains a point and a splitting dimension.
- Splitting: At each level, the space is split along a chosen dimension (cycling through dimensions).
- Left and Right Subtrees: Points less than the splitting value go to the left subtree, and greater/equal go to the right.
- Leaf Nodes: Leaf nodes contain points without further splitting.
Diagram: (3, 6)
/ \
(2, 7) (17, 15)
/ \ / \
(1, 5) (4, 2) (13, 15) (19, 20) Above is a 2-D tree (2-dimensional K-D Tree)- Root: (3, 6)
- The left child of the root is split on the x-coordinate, and the right child is split on the y-coordinate.
- This pattern continues, alternating between x and y at each level.
ImplementationNode Structure:- A class to store point coordinates, splitting dimension, and left/right child references.
Construction:- Recursively split data along the median of a chosen dimension.
- Base case: If the number of points is small, create a leaf node.
Insertion:- Traverse the tree based on splitting dimensions and values, inserting at the appropriate leaf.
Basic Operations and Complexities:Nearest Neighbor Search:- Start at the root, traverse to the leaf containing the query point.
- Backtrack, checking sibling nodes if they might contain closer points.
- Average Time Complexity: O(log n)
Range Search:- Similar to nearest neighbor, but explore regions overlapping the query range.
- Time Complexity: O(k + log n), where k is the number of reported points.
- Space Complexity: O(n) due to storing all points.
Java Program to Construct K-D Tree
Java
// Java Program to Construct K-D Tree
import java.util.Arrays;
class KDTree {
// Dimension of the space
private static final int K = 2;
static class Node {
int[] point; // Array to store k dimensional point
Node left, right; // Left and right child
public Node(int[] arr)
{
// Copy the point array
this.point = Arrays.copyOf(arr, K);
// Initialize children
this.left = this.right = null;
}
}
Node root; // Root of the K-D Tree
KDTree()
{
root = null; // Initialize the root
}
// Recursive method to insert a new point in the subtree
// rooted with the given node
Node insertRec(Node root, int[] point, int depth)
{
// Base case: If the tree is empty, return a new
// node
if (root == null) {
return new Node(point);
}
// Calculate current dimension (cd) of comparison
int cd = depth % K;
// Compare the new point with the root on current
// dimension and decide the left or right subtree
if (point[cd] < root.point[cd]) {
root.left
= insertRec(root.left, point, depth + 1);
}
else {
root.right
= insertRec(root.right, point, depth + 1);
}
return root;
}
// Method to insert a new point in the K-D Tree
void insert(int[] point)
{
root = insertRec(root, point, 0);
}
// Recursive method to search a point in the subtree
// rooted with the given node
boolean searchRec(Node root, int[] point, int depth)
{
// Base case: The tree is empty or the point is
// present at root
if (root == null) {
return false;
}
if (Arrays.equals(root.point, point)) {
return true;
}
// Calculate current dimension (cd)
int cd = depth % K;
// Compare the point with the root on current
// dimension and decide the left or right subtree
if (point[cd] < root.point[cd]) {
return searchRec(root.left, point, depth + 1);
}
else {
return searchRec(root.right, point, depth + 1);
}
}
// Method to search a point in the K-D Tree
boolean search(int[] point)
{
return searchRec(root, point, 0);
}
// Recursive method for range search in the subtree
// rooted with the given node
void rangeSearchRec(Node root, int[] lower, int[] upper,
int depth)
{
if (root == null) {
return;
}
// Check if the point of root is in range
boolean inside = true;
for (int i = 0; i < K; i++) {
if (root.point[i] < lower[i]
|| root.point[i] > upper[i]) {
inside = false;
break;
}
}
// If the point is in range, print it
if (inside) {
System.out.println(Arrays.toString(root.point));
}
// Calculate current dimension (cd)
int cd = depth % K;
// Check subtrees if they can have points within the
// range
if (lower[cd] <= root.point[cd]) {
rangeSearchRec(root.left, lower, upper,
depth + 1);
}
if (upper[cd] >= root.point[cd]) {
rangeSearchRec(root.right, lower, upper,
depth + 1);
}
}
// Method for range search
void rangeSearch(int[] lower, int[] upper)
{
rangeSearchRec(root, lower, upper, 0);
}
public static void main(String[] args)
{
KDTree tree = new KDTree();
int[][] points
= { { 3, 6 }, { 17, 15 }, { 13, 15 }, { 6, 12 },
{ 9, 1 }, { 2, 7 }, { 10, 19 } };
// Insert points into the K-D Tree
for (int[] point : points) {
tree.insert(point);
}
// Search for specific points in the K-D Tree
System.out.println(
tree.search(new int[] { 10, 19 })); // true
System.out.println(
tree.search(new int[] { 12, 19 })); // false
// Range search for points within the specified
// range
int[] lower = { 0, 0 };
int[] upper = { 10, 10 };
// Print points within range
tree.rangeSearch(lower, upper);
}
}
Outputtrue
false
[3, 6]
[2, 7]
[9, 1]
Complexity Table:
Operation
| Average Time Complexity
| Worst Time Complexity
| Space Complexity
|
---|
Insertion
| O(log N)
| O(N)
| O(N)
|
---|
Search
| O(log N)
| O(N)
| O(1)
|
---|
Range Search
| O(sqrt(N) + k)
| O(N)
| O(1)
|
---|
Nearest Neighbor
| O(log N)
| O(N)
| O(1)
|
---|
Applications- Nearest Neighbor Search: Finding similar items (e.g., recommendations).
- Database Indexing: Efficiently searching for data based on multiple attributes.
- Collision Detection: In computer graphics and simulations.
- Data Compression: Vector quantization techniques.
|