Java Program to Find Nearest Neighbour for Static Data Set

This is a Java Program to implement 2D KD Tree and find the nearest neighbor for static input set. In computer science, a k-d tree (short for k-dimensional tree) is a space-partitioning data structure for organizing points in a k-dimensional space. k-d trees are a useful data structure for several applications, such as searches involving a multidimensional search key (e.g. range searches and nearest neighbor searches). k-d trees are a special case of binary space partitioning trees.

Here is the source code of the Java Program to Find Nearest Neighbor for Static Data Set. The Java program is successfully compiled and run on a Windows system. The program output is also shown below.

  1. //This is a java program to find the nearest neighbor for the static data set
  2. import java.io.IOException;
  3. import java.util.Scanner;
  4.  
  5. class KDNodes
  6. {
  7.     int axis;
  8.     double[] x;
  9.     int id;
  10.     boolean checked;
  11.     boolean orientation;
  12.  
  13.     KDNodes Parent;
  14.     KDNodes Left;
  15.     KDNodes Right;
  16.  
  17.     public KDNodes(double[] x0, int axis0)
  18.     {
  19.         x = new double[2];
  20.         axis = axis0;
  21.         for (int k = 0; k < 2; k++)
  22.             x[k] = x0[k];
  23.  
  24.         Left = Right = Parent = null;
  25.         checked = false;
  26.         id = 0;
  27.     }
  28.  
  29.     public KDNodes FindParent(double[] x0)
  30.     {
  31.         KDNodes parent = null;
  32.         KDNodes next = this;
  33.         int split;
  34.         while (next != null)
  35.         {
  36.             split = next.axis;
  37.             parent = next;
  38.             if (x0[split] > next.x[split])
  39.                 next = next.Right;
  40.             else
  41.                 next = next.Left;
  42.         }
  43.         return parent;
  44.     }
  45.  
  46.     public KDNodes Insert(double[] p)
  47.     {
  48.         x = new double[2];
  49.         KDNodes parent = FindParent(p);
  50.         if (equal(p, parent.x, 2) == true)
  51.             return null;
  52.  
  53.         KDNodes newNode = new KDNodes(p, parent.axis + 1 < 2 ? parent.axis + 1
  54.                 : 0);
  55.         newNode.Parent = parent;
  56.  
  57.         if (p[parent.axis] > parent.x[parent.axis])
  58.         {
  59.             parent.Right = newNode;
  60.             newNode.orientation = true; //
  61.         } else
  62.         {
  63.             parent.Left = newNode;
  64.             newNode.orientation = false; //
  65.         }
  66.  
  67.         return newNode;
  68.     }
  69.  
  70.     boolean equal(double[] x1, double[] x2, int dim)
  71.     {
  72.         for (int k = 0; k < dim; k++)
  73.         {
  74.             if (x1[k] != x2[k])
  75.                 return false;
  76.         }
  77.  
  78.         return true;
  79.     }
  80.  
  81.     double distance2(double[] x1, double[] x2, int dim)
  82.     {
  83.         double S = 0;
  84.         for (int k = 0; k < dim; k++)
  85.             S += (x1[k] - x2[k]) * (x1[k] - x2[k]);
  86.         return S;
  87.     }
  88. }
  89.  
  90. class KDTreeStatic
  91. {
  92.     KDNodes Root;
  93.  
  94.     int TimeStart, TimeFinish;
  95.     int CounterFreq;
  96.  
  97.     double d_min;
  98.     KDNodes nearest_neighbour;
  99.  
  100.     int KD_id;
  101.  
  102.     int nList;
  103.  
  104.     KDNodes CheckedNodes[];
  105.     int checked_nodes;
  106.     KDNodes List[];
  107.  
  108.     double x_min[], x_max[];
  109.     boolean max_boundary[], min_boundary[];
  110.     int n_boundary;
  111.  
  112.     public KDTreeStatic(int i)
  113.     {
  114.         Root = null;
  115.         KD_id = 1;
  116.         nList = 0;
  117.         List = new KDNodes[i];
  118.         CheckedNodes = new KDNodes[i];
  119.         max_boundary = new boolean[2];
  120.         min_boundary = new boolean[2];
  121.         x_min = new double[2];
  122.         x_max = new double[2];
  123.     }
  124.  
  125.     public boolean add(double[] x)
  126.     {
  127.         if (nList >= 2000000 - 1)
  128.             return false; // can't add more points
  129.  
  130.         if (Root == null)
  131.         {
  132.             Root = new KDNodes(x, 0);
  133.             Root.id = KD_id++;
  134.             List[nList++] = Root;
  135.         } else
  136.         {
  137.             KDNodes pNode;
  138.             if ((pNode = Root.Insert(x)) != null)
  139.             {
  140.                 pNode.id = KD_id++;
  141.                 List[nList++] = pNode;
  142.             }
  143.         }
  144.  
  145.         return true;
  146.     }
  147.  
  148.     public KDNodes find_nearest(double[] x)
  149.     {
  150.         if (Root == null)
  151.             return null;
  152.  
  153.         checked_nodes = 0;
  154.         KDNodes parent = Root.FindParent(x);
  155.         nearest_neighbour = parent;
  156.         d_min = Root.distance2(x, parent.x, 2);
  157.         ;
  158.  
  159.         if (parent.equal(x, parent.x, 2) == true)
  160.             return nearest_neighbour;
  161.  
  162.         search_parent(parent, x);
  163.         uncheck();
  164.  
  165.         return nearest_neighbour;
  166.     }
  167.  
  168.     public void check_subtree(KDNodes node, double[] x)
  169.     {
  170.         if ((node == null) || node.checked)
  171.             return;
  172.  
  173.         CheckedNodes[checked_nodes++] = node;
  174.         node.checked = true;
  175.         set_bounding_cube(node, x);
  176.  
  177.         int dim = node.axis;
  178.         double d = node.x[dim] - x[dim];
  179.  
  180.         if (d * d > d_min)
  181.         {
  182.             if (node.x[dim] > x[dim])
  183.                 check_subtree(node.Left, x);
  184.             else
  185.                 check_subtree(node.Right, x);
  186.         } else
  187.         {
  188.             check_subtree(node.Left, x);
  189.             check_subtree(node.Right, x);
  190.         }
  191.     }
  192.  
  193.     public void set_bounding_cube(KDNodes node, double[] x)
  194.     {
  195.         if (node == null)
  196.             return;
  197.         int d = 0;
  198.         double dx;
  199.         for (int k = 0; k < 2; k++)
  200.         {
  201.             dx = node.x[k] - x[k];
  202.             if (dx > 0)
  203.             {
  204.                 dx *= dx;
  205.                 if (!max_boundary[k])
  206.                 {
  207.                     if (dx > x_max[k])
  208.                         x_max[k] = dx;
  209.                     if (x_max[k] > d_min)
  210.                     {
  211.                         max_boundary[k] = true;
  212.                         n_boundary++;
  213.                     }
  214.                 }
  215.             } else
  216.             {
  217.                 dx *= dx;
  218.                 if (!min_boundary[k])
  219.                 {
  220.                     if (dx > x_min[k])
  221.                         x_min[k] = dx;
  222.                     if (x_min[k] > d_min)
  223.                     {
  224.                         min_boundary[k] = true;
  225.                         n_boundary++;
  226.                     }
  227.                 }
  228.             }
  229.             d += dx;
  230.             if (d > d_min)
  231.                 return;
  232.  
  233.         }
  234.  
  235.         if (d < d_min)
  236.         {
  237.             d_min = d;
  238.             nearest_neighbour = node;
  239.         }
  240.     }
  241.  
  242.     public KDNodes search_parent(KDNodes parent, double[] x)
  243.     {
  244.         for (int k = 0; k < 2; k++)
  245.         {
  246.             x_min[k] = x_max[k] = 0;
  247.             max_boundary[k] = min_boundary[k] = false; //
  248.         }
  249.         n_boundary = 0;
  250.  
  251.         KDNodes search_root = parent;
  252.         while (parent != null && (n_boundary != 2 * 2))
  253.         {
  254.             check_subtree(parent, x);
  255.             search_root = parent;
  256.             parent = parent.Parent;
  257.         }
  258.  
  259.         return search_root;
  260.     }
  261.  
  262.     public void uncheck()
  263.     {
  264.         for (int n = 0; n < checked_nodes; n++)
  265.             CheckedNodes[n].checked = false;
  266.     }
  267.  
  268. }
  269.  
  270. public class Static_Nearest
  271. {
  272.  
  273.     public static void main(String args[]) throws IOException
  274.     {
  275.         int numpoints = 7;
  276.         Scanner sc = new Scanner(System.in);
  277.         KDTreeStatic kdt = new KDTreeStatic(numpoints);
  278.         double x[] = new double[2];
  279.  
  280.         x[0] = 2.1;
  281.         x[1] = 4.3;
  282.         kdt.add(x);
  283.  
  284.         x[0] = 3.3;
  285.         x[1] = 1.5;
  286.         kdt.add(x);
  287.  
  288.         x[0] = 4.7;
  289.         x[1] = 11.1;
  290.         kdt.add(x);
  291.  
  292.         x[0] = 5.0;
  293.         x[1] = 12.3;
  294.         kdt.add(x);
  295.  
  296.         x[0] = 5.1;
  297.         x[1] = 1.2;
  298.         kdt.add(x);
  299.  
  300.         x[0] = 12.1;
  301.         x[1] = 18.2;
  302.         kdt.add(x);
  303.  
  304.         x[0] = 20.5;
  305.         x[1] = 17.9;
  306.         kdt.add(x);
  307.  
  308.         System.out.println("Enter the co-ordinates of the point: <x> <y>");
  309.  
  310.         double sx = sc.nextDouble();
  311.         double sy = sc.nextDouble();
  312.  
  313.         double s[] = { sx, sy };
  314.         KDNodes kdn = kdt.find_nearest(s);
  315.         System.out.println("The nearest neighbor for the static data set is: ");
  316.         System.out.println("(" + kdn.x[0] + " , " + kdn.x[1] + ")");
  317.         sc.close();
  318.     }
  319. }

Output:

$ javac Static_Nearest.java
$ java Static_Nearest
 
Enter the co-ordinates of the point: <x> <y>
9 9
The nearest neighbor for the static data set is: 
(4.7 , 11.1)
 
Enter the co-ordinates of the point: <x> <y>
5 20
The nearest neighbor for the static data set is: 
(12.1 , 18.2)

Sanfoundry Global Education & Learning Series – 1000 Java Programs.

advertisement
advertisement

Here’s the list of Best Books in Java Programming, Data Structures and Algorithms.

If you find any mistake above, kindly email to [email protected]

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.