K-Dimensional (K-D) Trees in Datastructures



The K-D is a multi-dimensional binary search tree. It is defined as a data structure for storing multikey records. This structure has been implemented to solve a number of "geometric" problems in statistics and data analysis.

A k-d tree (short for k-dimensional tree) is defined as a space-partitioning data structure for organizing points in a k-dimensional space. Data structure k-d trees are implemented for several applications, for example, searches involving a multidimensional search key (e.g. range searches and nearest neighbor searches). k-d trees are treated as a special case of binary space partitioning trees.

Properties of K-D Trees

Following are the properties of k-d trees:

  • The depth of the k-d tree is O(log n) where n is the number of points.
  • Each node in the tree contains a k-dimensional point and pointers to the left and right child nodes.
  • The choice of the axis at each level of the tree follows a cycle through the axes.
  • And choice of axis at each level will affect's the tree's performance in terms of search speed.

Operations on K-D Trees

Following are the operations that can be performed on k-d trees:

  • Insert(x): Insert a point x into the k-d tree.
  • Delete(x): Delete a point x from the k-d tree.
  • Search(x): Search for a point x in the k-d tree.

Construction of K-D Trees

The construction of k-d trees is done by using recursive partitioning. The steps to construct a k-d tree are as follows:

  • Choose the axis of the splitting plane.
  • Choose the median as the pivot element.
  • Split the points into two sets: one set contains points less than the median and the other set contains points greater than the median.
  • Repeat the above steps for the left and right subtrees.

Now, let's code the construction of k-d trees:

Code to Construct K-D Trees and Insert Operation

We performed insert operation in order to construct a k-d tree.

Following is the example code to construct a k-d tree in C, C++, Java, and Python:

#include <stdio.h>
#include <stdlib.h>

// Structure to represent a node of the k-d tree
struct Node {
   int point[2];
   struct Node *left, *right;
};

// Function to create a new node
struct Node* newNode(int arr[]) {
   struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
   temp->point[0] = arr[0];
   temp->point[1] = arr[1];
   temp->left = temp->right = NULL;
   return temp;
}

// Function to insert a new node
struct Node* insertNode(struct Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return newNode(point);

   unsigned cd = depth % 2;

   if (point[cd] < (root->point[cd]))
      root->left = insertNode(root->left, point, depth + 1);
   else
      root->right = insertNode(root->right, point, depth + 1);

   return root;
}

// Function to construct a k-d tree
struct Node* constructKdTree(int points[][2], int n) {
   struct Node* root = NULL;
   for (int i = 0; i < n; i++)
      root = insertNode(root, points[i], 0);
   return root;
}

// Function to print the k-d tree (Preorder Traversal)
void printKdTree(struct Node* root) {
   if (root == NULL)
      return;
   printf("(%d, %d)\n", root->point[0], root->point[1]);
   printKdTree(root->left);
   printKdTree(root->right);
}

// Main function
int main() {
   int points[][2] = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
   int n = sizeof(points) / sizeof(points[0]);
   struct Node* root = constructKdTree(points, n);
   printKdTree(root);
   return 0;
}

Output

(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
// C++ program to construct a k-d tree
#include <iostream>
using namespace std;

// Structure to represent a node of the k-d tree
struct Node {
   int point[2];
   Node *left, *right;
};

// Function to create a new node
Node* newNode(int arr[]) {
   Node* temp = new Node;
   temp->point[0] = arr[0];
   temp->point[1] = arr[1];
   temp->left = temp->right = NULL;
   return temp;
}

// Function to insert a new node
Node* insertNode(Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return newNode(point);

   unsigned cd = depth % 2;

   if (point[cd] < (root->point[cd]))
      root->left = insertNode(root->left, point, depth + 1);
   else
      root->right = insertNode(root->right, point, depth + 1);

   return root;
}

// Function to construct a k-d tree
Node* constructKdTree(int points[][2], int n) {
   Node* root = NULL;
   for (int i = 0; i < n; i++)
      root = insertNode(root, points[i], 0);
   return root;
}

// Function to print the k-d tree
void printKdTree(Node* root) {
   if (root == NULL)
      return;
   cout << "(" << root->point[0] << ", " << root->point[1] << ")" << endl;
   printKdTree(root->left);
   printKdTree(root->right);
}

// Main function
int main() {
   int points[][2] = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
   int n = sizeof(points) / sizeof(points[0]);
   Node* root = constructKdTree(points, n);
   printKdTree(root);
   return 0;
}

Output

Following is the output of the above code:

(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
// Java program to construct a k-d tree
class Node {
   int[] point;
   Node left, right;
   Node(int[] point) {
      this.point = point;
      this.left = this.right = null;
   }
}

public class KdTree {
   Node root;

   Node insertNode(Node root, int[] point, int depth) {
      if (root == null)
         return new Node(point);

      int cd = depth % 2;

      if (point[cd] < root.point[cd])
         root.left = insertNode(root.left, point, depth + 1);
      else
         root.right = insertNode(root.right, point, depth + 1);

      return root;
   }

   Node constructKdTree(int[][] points) {
      for (int i = 0; i < points.length; i++)
         root = insertNode(root, points[i], 0);
      return root;
   }

   void printKdTree(Node root) {
      if (root == null)
         return;
      System.out.println("(" + root.point[0] + ", " + root.point[1] + ")");
      printKdTree(root.left);
      printKdTree(root.right);
   }

   public static void main(String[] args) {
      int[][] points = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
      KdTree tree = new KdTree();
      tree.constructKdTree(points);
      tree.printKdTree(tree.root);
   }
}

Output

Following is the output of the above code:

(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
# Python program to construct a k-d tree
class Node:
   def __init__(self, point):
      self.point = point
      self.left = None
      self.right = None

def insertNode(root, point, depth):
    if root is None:
        return Node(point)
    
    cd = depth % 2
    
    if point[cd] < root.point[cd]:
        root.left = insertNode(root.left, point, depth + 1)
    else:
        root.right = insertNode(root.right, point, depth + 1)
    
    return root

def constructKdTree(points):
    root = None
    for point in points:
        root = insertNode(root, point, 0)
    return root

def printKdTree(root):
    if root is None:
        return
    print("(", root.point[0], ", ", root.point[1], ")")
    printKdTree(root.left)
    printKdTree(root.right)

points = [[3, 6], [17, 15], [13, 15], [6, 12], [9, 1], [2, 7], [10, 19]]
root = constructKdTree(points)
printKdTree(root)

Output

Following is the output of the above code:

(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)

Delete Operation on K-D Trees

The delete operation in k-d trees is performed by following the below steps:

  • Find the node to be deleted.
  • If the node is a leaf node, delete it directly.
  • If the node has only one child, replace the node with its child.
  • If the node has two children, find the inorder successor of the node, replace the node with the inorder successor, and delete the inorder successor.

Code to Delete a Node from K-D Trees

Following is the example code to delete a node from k-d trees in C, C++, Java, and Python:

// C program to delete a node from a k-d tree
#include <stdio.h>
#include <stdlib.h>

// Structure to represent a node of the k-d tree
struct Node {
   int point[2];
   struct Node *left, *right;
};

// Function to create a new node
struct Node* newNode(int arr[]) {
   struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
   temp->point[0] = arr[0];
   temp->point[1] = arr[1];
   temp->left = temp->right = NULL;
   return temp;
}

// Function to insert a new node
struct Node* insertNode(struct Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return newNode(point);

   unsigned cd = depth % 2;

   if (point[cd] < root->point[cd])
      root->left = insertNode(root->left, point, depth + 1);
   else
      root->right = insertNode(root->right, point, depth + 1);

   return root;
}

// Function to find the minimum value node in a k-d tree
struct Node* minValueNode(struct Node* root, int d, unsigned depth) {
   if (root == NULL)
      return NULL;

   unsigned cd = depth % 2;

   if (cd == d) {
      if (root->left == NULL)
         return root;
      return minValueNode(root->left, d, depth + 1);
   }

   struct Node* left = minValueNode(root->left, d, depth + 1);
   struct Node* right = minValueNode(root->right, d, depth + 1);

   struct Node* min = root;
   if (left != NULL && left->point[d] < min->point[d])
      min = left;
   if (right != NULL && right->point[d] < min->point[d])
      min = right;

   return min;
}

// Function to delete a node from the k-d tree
struct Node* deleteNode(struct Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return NULL;

   unsigned cd = depth % 2;

   if (root->point[0] == point[0] && root->point[1] == point[1]) {
      if (root->right != NULL) {
         struct Node* min = minValueNode(root->right, cd, depth + 1);
         root->point[0] = min->point[0];
         root->point[1] = min->point[1];
         root->right = deleteNode(root->right, min->point, depth + 1);
      } else if (root->left != NULL) {
         struct Node* min = minValueNode(root->left, cd, depth + 1);
         root->point[0] = min->point[0];
         root->point[1] = min->point[1];
         root->right = deleteNode(root->left, min->point, depth + 1);
         root->left = NULL;
      } else {
         free(root);
         return NULL;
      }
   } else if (point[cd] < root->point[cd]) {
      root->left = deleteNode(root->left, point, depth + 1);
   } else {
      root->right = deleteNode(root->right, point, depth + 1);
   }

   return root;
}

// Function to construct a k-d tree
struct Node* constructKdTree(int points[][2], int n) {
   struct Node* root = NULL;
   for (int i = 0; i < n; i++)
      root = insertNode(root, points[i], 0);
   return root;
}

// Function to print the k-d tree (Preorder Traversal)
void printKdTree(struct Node* root) {
   if (root == NULL)
      return;
   printf("(%d, %d)\n", root->point[0], root->point[1]);
   printKdTree(root->left);
   printKdTree(root->right);
}

// Main function
int main() {
   int points[][2] = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
   int n = sizeof(points) / sizeof(points[0]);
   struct Node* root = constructKdTree(points, n);
   
   printf("K-D Tree before deletion:\n");
   printKdTree(root);

   int deletePoint[] = {13, 15}; // Deleting (13, 15)
   root = deleteNode(root, deletePoint, 0);

   printf("K-D Tree after deletion:\n");
   printKdTree(root);

   return 0;
}

Output

K-D Tree before deletion:
(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
K-D Tree after deletion:
(3, 6)
(2, 7)
(17, 15)
(6, 12)
(9, 1)
(10, 19)
// C++ program to delete a node from a k-d tree
#include <iostream>
using namespace std;

// Structure to represent a node of the k-d tree
struct Node {
   int point[2];
   Node *left, *right;
};

// Function to create a new node
Node* newNode(int arr[]) {
   Node* temp = new Node;
   temp->point[0] = arr[0];
   temp->point[1] = arr[1];
   temp->left = temp->right = NULL;
   return temp;
}

// Function to insert a new node
Node* insertNode(Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return newNode(point);

   unsigned cd = depth % 2;

   if (point[cd] < (root->point[cd]))
      root->left = insertNode(root->left, point, depth + 1);
   else
      root->right = insertNode(root->right, point, depth + 1);

   return root;
}

// Function to find the minimum value node
Node* minValueNode(Node* root, int d, unsigned depth) {
   if (root == NULL)
      return NULL;

   unsigned cd = depth % 2;

   if (cd == d) {
      if (root->left == NULL)
         return root;
      return minValueNode(root->left, d, depth + 1);
   }

   Node* left = minValueNode(root->left, d, depth + 1);
   Node* right = minValueNode(root->right, d, depth + 1);

   Node* min = root;
   if (left != NULL && left->point[d] < min->point[d])
      min = left;
   if (right != NULL && right->point[d] < min->point[d])
      min = right;

   return min;
}

// Function to delete a node

Node* deleteNode(Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return NULL;

   unsigned cd = depth % 2;

   if (root->point[0] == point[0] && root->point[1] == point[1]) {
      if (root->right != NULL) {
         Node* min = minValueNode(root->right, cd, depth + 1);
         root->point[0] = min->point[0];
         root->point[1] = min->point[1];
         root->right = deleteNode(root->right, min->point, depth + 1);
      } else if (root->left != NULL) {
         Node* min = minValueNode(root->left, cd, depth + 1);
         root->point[0] = min->point[0];
         root->point[1] = min->point[1];
         root->right = deleteNode(root->left, min->point, depth + 1);
         root->left = NULL;
      } else
         return NULL;
   } else if (point[cd] < root->point[cd])
      root->left = deleteNode(root->left, point, depth + 1);
   else
      root->right = deleteNode(root->right, point, depth + 1);

   return root;
}

// Function to construct a k-d tree
Node* constructKdTree(int points[][2], int n) {
   Node* root = NULL;
   for (int i = 0; i < n; i++)
      root = insertNode(root, points[i], 0);
   return root;
}

// Function to print the k-d tree
void printKdTree(Node* root) {
   if (root == NULL)
      return;
   cout << "(" << root->point[0] << ", " << root->point[1] << ")" << endl;
   printKdTree(root->left);
   printKdTree(root->right);
}

// Main function
int main() {
   int points[][2] = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
   int n = sizeof(points) / sizeof(points[0]);
   Node* root = constructKdTree(points, n);
   cout << "K-D Tree before deletion:" << endl;
   printKdTree(root);
   root = deleteNode(root, points[2], 0);
   cout << "K-D Tree after deletion:" << endl;
   printKdTree(root);
   return 0;
}

Output

Following is the output of the above code:

K-D Tree before deletion:
(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
K-D Tree after deletion:
(3, 6)
(2, 7)
(17, 15)
(6, 12)
(9, 1)
(10, 19)
// Java program to delete a node from a k-d tree
class Node {
   int[] point;
   Node left, right;
   Node(int[] point) {
      this.point = point;
      this.left = this.right = null;
   }
}

public class KdTree {
   Node root;

   Node insertNode(Node root, int[] point, int depth) {
      if (root == null)
         return new Node(point);

      int cd = depth % 2;

      if (point[cd] < root.point[cd])
         root.left = insertNode(root.left, point, depth + 1);
      else
         root.right = insertNode(root.right, point, depth + 1);

      return root;
   }

   Node minValueNode(Node root, int d, int depth) {
      if (root == null)
         return null;

      int cd = depth % 2;

      if (cd == d) {
         if (root.left == null)
            return root;
         return minValueNode(root.left, d, depth + 1);
      }

      Node left = minValueNode(root.left, d, depth + 1);
      Node right = minValueNode(root.right, d, depth + 1);

      Node min = root;
      if (left != null && left.point[d] < min.point[d])
         min = left;
      if (right != null && right.point[d] < min.point[d])
         min = right;

      return min;
   }

   Node deleteNode(Node root, int[] point, int depth) {
      if (root == null)
         return null;

      int cd = depth % 2;

      if (root.point[0] == point[0] && root.point[1] == point[1]) {
         if (root.right != null) {
            Node min = minValueNode(root.right, cd, depth + 1);
            root.point[0] = min.point[0];
            root.point[1] = min.point[1];
            root.right = deleteNode(root.right, min.point, depth + 1);
         } else if (root.left != null) {
            Node min = minValueNode(root.left, cd, depth + 1);
            root.point[0] = min.point[0];
            root.point[1] = min.point[1];
            root.right = deleteNode(root.left, min.point, depth + 1);
            root.left = null;
         } else
            return null;
      } else if (point[cd] < root.point[cd])
         root.left = deleteNode(root.left, point, depth + 1);
        else
            root.right = deleteNode(root.right, point, depth + 1);

        return root;
    }

    void printKdTree(Node root) {
        if (root == null)
            return;
        System.out.println("(" + root.point[0] + ", " + root.point[1] + ")");
        printKdTree(root.left);
        printKdTree(root.right);
    }

    public static void main(String[] args) {
        int[][] points = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
        KdTree tree = new KdTree();
        for (int[] point : points)
            tree.root = tree.insertNode(tree.root, point, 0);
        System.out.println("K-D Tree before deletion:");
        tree.printKdTree(tree.root);
        tree.root = tree.deleteNode(tree.root, points[2], 0);
        System.out.println("K-D Tree after deletion:");
        tree.printKdTree(tree.root);
    }
}

Output

Following is the output of the above code:

K-D Tree before deletion:
(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
K-D Tree after deletion:
(3, 6)
(2, 7)
(17, 15)
(6, 12)
(9, 1)
(10, 19)
# Python program to delete a node from a k-d tree
class Node:
   def __init__(self, point):
      self.point = point
      self.left = None
      self.right = None

def insertNode(root, point, depth):

    if root is None:
        return Node(point)
    
    cd = depth % 2
    
    if point[cd] < root.point[cd]:
        root.left = insertNode(root.left, point, depth + 1)
    else:
        root.right = insertNode(root.right, point, depth + 1)
    
    return root

def minValueNode(root, d, depth):

    if root is None:
        return None
    
    cd = depth % 2
    
    if cd == d:
        if root.left is None:
            return root
        return minValueNode(root.left, d, depth + 1)
    
    left = minValueNode(root.left, d, depth + 1)
    right = minValueNode(root.right, d, depth + 1)
    
    min = root
    if left is not None and left.point[d] < min.point[d]:
        min = left
    if right is not None and right.point[d] < min.point[d]:
        min = right
    
    return min

def deleteNode(root, point, depth):

    if root is None:
        return None
    
    cd = depth % 2
    
    if root.point[0] == point[0] and root.point[1] == point[1]:
        if root.right is not None:
            min = minValueNode(root.right, cd, depth + 1)
            root.point[0] = min.point[0]
            root.point[1] = min.point[1]
            root.right = deleteNode(root.right, min.point, depth + 1)
        elif root.left is not None:
            min = minValueNode(root.left, cd, depth + 1)
            root.point[0] = min.point[0]
            root.point[1] = min.point[1]
            root.right = deleteNode(root.left, min.point, depth + 1)
            root.left = None
        else:
            return None
    elif point[cd] < root.point[cd]:
        root.left = deleteNode(root.left, point, depth + 1)
    else:
        root.right = deleteNode(root.right, point, depth + 1)
    
    return root

def printKdTree(root):
    if root is None:
        return
    print("(", root.point[0], ", ", root.point[1], ")")
    printKdTree(root.left)
    printKdTree(root.right)

points = [[3, 6], [17, 15], [13, 15], [6, 12], [9, 1], [2, 7], [10, 19]]
root = None
for point in points:
    root = insertNode(root, point, 0)
print("K-D Tree before deletion:")
printKdTree(root)
root = deleteNode(root, points[2], 0)
print("K-D Tree after deletion:")
printKdTree(root)

Output

Following is the output of the above code:

K-D Tree before deletion:
(3, 6)
(2, 7)
(17, 15)
(13, 15)
(6, 12)
(9, 1)
(10, 19)
K-D Tree after deletion:
(3, 6)
(2, 7)
(17, 15)
(6, 12)
(9, 1)
(10, 19)

Search Operation on K-D Trees

The search operation in k-d trees is performed by following the below steps:

  • Start from the root node.
  • If the point is equal to the root node, return the root node.
  • If the point is less than the root node, search in the left subtree.
  • If the point is greater than the root node, search in the right subtree.

Code to Search a Node in K-D Trees

Following is the example code to search a node in k-d trees in C, C++, Java, and Python:

#include <stdio.h>
#include <stdlib.h>

// Structure to represent a node of the k-d tree
struct Node {
   int point[2];
   struct Node *left, *right;
};

// Function to create a new node
struct Node* newNode(int arr[]) {
   struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
   temp->point[0] = arr[0];
   temp->point[1] = arr[1];
   temp->left = temp->right = NULL;
   return temp;
}

// Function to insert a new node
struct Node* insertNode(struct Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return newNode(point);

   unsigned cd = depth % 2;

   if (point[cd] < root->point[cd])
      root->left = insertNode(root->left, point, depth + 1);
   else
      root->right = insertNode(root->right, point, depth + 1);

   return root;
}

// Function to search a node in a k-d tree
struct Node* searchNode(struct Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return NULL;

   if (root->point[0] == point[0] && root->point[1] == point[1])
      return root;

   unsigned cd = depth % 2;

   if (point[cd] < root->point[cd])
      return searchNode(root->left, point, depth + 1);
   return searchNode(root->right, point, depth + 1);
}

// Function to construct a k-d tree
struct Node* constructKdTree(int points[][2], int n) {
   struct Node* root = NULL;
   for (int i = 0; i < n; i++)
      root = insertNode(root, points[i], 0);
   return root;
}


// Function to free memory allocated for the k-d tree
void freeKdTree(struct Node* root) {
   if (root == NULL)
      return;
   freeKdTree(root->left);
   freeKdTree(root->right);
   free(root);
}

// Main function
int main() {
   int points[][2] = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
   int n = sizeof(points) / sizeof(points[0]);
   struct Node* root = constructKdTree(points, n);


   int searchPoint[] = {13, 15}; // Searching for (13, 15)
   struct Node* node = searchNode(root, searchPoint, 0);

   if (node != NULL)
      printf("Node found: (%d, %d)\n", node->point[0], node->point[1]);
   else
      printf("Node not found\n");

   // Free allocated memory
   freeKdTree(root);

   return 0;
}

Output

Node found: (13, 15)
// C++ program to search a node in a k-d tree
#include <iostream>
using namespace std;

// Structure to represent a node of the k-d tree
struct Node {
   int point[2];
   Node *left, *right;
};

// Function to create a new node
Node* newNode(int arr[]) {
   Node* temp = new Node;
   temp->point[0] = arr[0];
   temp->point[1] = arr[1];
   temp->left = temp->right = NULL;
   return temp;
}

// Function to insert a new node
Node* insertNode(Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return newNode(point);

   unsigned cd = depth % 2;

   if (point[cd] < (root->point[cd]))
      root->left = insertNode(root->left, point, depth + 1);
   else
      root->right = insertNode(root->right, point, depth + 1);

   return root;
}

// Function to search a node
Node* searchNode(Node* root, int point[], unsigned depth) {
   if (root == NULL)
      return NULL;

   unsigned cd = depth % 2;

   if (root->point[0] == point[0] && root->point[1] == point[1])
      return root;

   if (point[cd] < root->point[cd])
      return searchNode(root->left, point, depth + 1);
   return searchNode(root->right, point, depth + 1);
}

// Function to construct a k-d tree

Node* constructKdTree(int points[][2], int n) {
   Node* root = NULL;
   for (int i = 0; i < n; i++)
      root = insertNode(root, points[i], 0);
   return root;
}

// Function to print the k-d tree
void printKdTree(Node* root) {
   if (root == NULL)
      return;
   cout << "(" << root->point[0] << ", " << root->point[1] << ")" << endl;
   printKdTree(root->left);
   printKdTree(root->right);
}

// Main function

int main() {
   int points[][2] = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
   int n = sizeof(points) / sizeof(points[0]);
   Node* root = constructKdTree(points, n);
   Node* node = searchNode(root, points[2], 0);
   if (node != NULL)
      cout << "Node found: (" << node->point[0] << ", " << node->point[1] << ")" << endl;
   else
      cout << "Node not found" << endl;
   return 0;
}

Output

Following is the output of the above code:

Node found: (13, 15)
// Java program to search a node in a k-d tree
class Node {
   int[] point;
   Node left, right;
   Node(int[] point) {
      this.point = point;
      this.left = this.right = null;
   }
}

public class KdTree {
   Node root;

   Node insertNode(Node root, int[] point, int depth) {
      if (root == null)
         return new Node(point);

      int cd = depth % 2;

      if (point[cd] < root.point[cd])
         root.left = insertNode(root.left, point, depth + 1);
      else
         root.right = insertNode(root.right, point, depth + 1);

      return root;
   }

   Node searchNode(Node root, int[] point, int depth) {
      if (root == null)
         return null;

      int cd = depth % 2;

      if (root.point[0] == point[0] && root.point[1] == point[1])
         return root;

      if (point[cd] < root.point[cd])
         return searchNode(root.left, point, depth + 1);
      return searchNode(root.right, point, depth + 1);
   }

   void printKdTree(Node root) {
      if (root == null)
         return;
      System.out.println("(" + root.point[0] + ", " + root.point[1] + ")");
      printKdTree(root.left);
      printKdTree(root.right);
   }

   public static void main(String[] args) {
      int[][] points = {{3, 6}, {17, 15}, {13, 15}, {6, 12}, {9, 1}, {2, 7}, {10, 19}};
      KdTree tree = new KdTree();
      for (int[] point : points)
         tree.root = tree.insertNode(tree.root, point, 0);
      Node node = tree.searchNode(tree.root, points[2], 0);
      if (node != null)
         System.out.println("Node found: (" + node.point[0] + ", " + node.point[1] + ")");
      else
         System.out.println("Node not found");
   }
}

Output

Following is the output of the above code:

Node found: (13, 15)
# Python program to search a node in a k-d tree

class Node:
   def __init__(self, point):
      self.point = point
      self.left = None
      self.right = None

def insertNode(root, point, depth):
    if root is None:
        return Node(point)
    
    cd = depth % 2
    
    if point[cd] < root.point[cd]:
        root.left = insertNode(root.left, point, depth + 1)
    else:
        root.right = insertNode(root.right, point, depth + 1)
    
    return root

def searchNode(root, point, depth):
    if root is None:
        return None
    
    cd = depth % 2
    
    if root.point[0] == point[0] and root.point[1] == point[1]:
        return root
    
    if point[cd] < root.point[cd]:
        return searchNode(root.left, point, depth + 1)
    return searchNode(root.right, point, depth + 1)

def printKdTree(root):
    if root is None:
        return
    print("(", root.point[0], ", ", root.point[1], ")")
    printKdTree(root.left)
    printKdTree(root.right)

points = [[3, 6], [17, 15], [13, 15], [6, 12], [9, 1], [2, 7], [10, 19]]
root = None
for point in points:
    root = insertNode(root, point, 0)
node = searchNode(root, points[2], 0)
if node is not None:
    print("Node found: (", node.point[0], ", ", node.point[1], ")")
else:
    print("Node not found")

Output

Following is the output of the above code:

Node found: (13, 15)

Time Complexity of K-D Trees

The time complexity of k-d trees for various operations is as follows:

  • Insertion: The time complexity of inserting a node in a k-d tree is O(log n), where n is the number of nodes in the tree.
  • Deletion: O(log n).
  • Search: O(log n).

Applications of K-D Trees

K-D trees are used in the following applications:

  • Nearest Neighbor Search: K-D trees are used for finding the nearest neighbor of a given point in a k-dimensional space.
  • Range Search: K-D trees are used to find all points within a given range of a query point.
  • Approximate Nearest Neighbor Search: K-D trees are used to find an approximate nearest neighbor of a given point in a k-dimensional space.
  • Image Processing: K-D trees are used in image processing to find similar images.

Conclusion

In this chapter, we discussed k-d trees, which are a data structure used for storing k-dimensional points. We discussed the construction of k-d trees, operations on k-d trees, and the time complexity of k-d trees. We also provided example code to construct, insert, delete, and search nodes in k-d trees in C, C++, Java, and Python.

Advertisements
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy