The program: Range Search

  • Due March 24 (Fri.), 2017, 11:59pm

Files

  • Source code: You will start your code from scratch. I would suggest that you create two java files. Main.java for console interaction and RangeTree.java for the range tree data structure. See details below.
  • Additional Files: README.txt, data01.txt, data02.txt, data03.txt (a few more example inputs will be given)

Change logs

  • Queries are now part of the input file, see details posted below on March 19, 2017
  • Two more dataset are posted on March 16, 2017
  • Output format: Print the points in sorted order. That is, sort the points by x coordinates in ascending order. If two points have the same x coordinate, the point with smaller y should be printed. If two points have the same x, and y coordinates, the point with smaller z should be printed.
  • Two more pseudocode added for 3D range search and tree construction on March 10, 2017, at 1:10 AM
  • Updated "Input" section on March 05, 2017, at 3:10 PM
  • Added a new section called "Pseudo code" on March 05, 2017, at 3:10 PM
  • Assignment created on March 02, 2017, at 12:22 AM

Description

Given a set of 3D points, the problem of range search takes a 3D range, such as a 3D box or a 3D ball, and reports all points inside the range. In this assignment, you will implement a data structure called range tree. Wikipedia provides a pretty good introduction on range tree, which in nutshell is a k-dimensional binary tree. In this assignment k=3. Range tree allows efficient orthogonal range search.

This picture shows an example of 2D range search.

1D Range search

1D range tree is basically a balanced binary search tree.

  • The leaves of the tree store the points
  • The internal nodes of T store splitting values to guide the search, i.e., the largest value in the left sub-tree

Searching in a range tree requires you to determine the split node where the paths to x and x' splits. Here x and x' are the lower and upper bound of the range. The example below shows the range search of [6, 16]. The split node is node 14.

2D Range tree

An example of a 2D range tree is shown below. 2D Range tree has two levels

  • First level is a 1D BST on x-axis (x-BST)
  • For each node of x-BST, we build a 1D BST on y-axis for values in the sub-tree

We can perform the 2D range query similarly by only visiting the associated binary search tree on y-coordinate of the sub-tree of v, whose x-coordinate lies in the x-interval of the query rectangle

Input

Example input. This will be stored in a file.

Format

  • the first line is a positive integer n>=1, indicate the number of points in this file
  • the next n lines, contains n 3D points (x, y, z), numbers will be given. No need to check if they are actually number.
  • Queries , the input points will be followed by lines of queries until a line containing only "exit" is reahed.
    • Queries are in the format of min_x max_x min_y max_y min_z max_z
    • Your code should check if they are actually numbers.
    • The users might make mistakes and mixed up min and max. You code should swap min and max if min is greater than max.
    • When a keyword exist is given. Your code prints out "bye" and terminates.
10
0.366	0.136	0.009
0.082	0.791	0.832
0.138	0.968	0.391
0.414	0.785	0.883
0.546	0.044	0.133
0.513	0.612	0.466
0.415	0.640	0.099
0.199	0.999	0.086
0.896	0.835	0.860
0.091	0.719	0.772
0.25 0.75 0.25 0.75 0.25 0.75
0.75 0.25 0.8 0.1 0.9 0.1
0.95 1.75 0.1 0.01 0.1 0.2
exit

Example run.

java rtree < input_file
Read in 10 points
Query: 0.25 0.75 0.25 0.75 0.25 0.75
Found 1 point
0.513	0.612	0.466

Query: 0.75 0.25 0.8 0.1 0.9 0.1
Found 2 points
0.414	0.785	0.883
0.513	0.612	0.466

Query:  0.95 1.75 0.1 0.01 0.1 0.2
Found 0 point

Query:  exit
bye
  • Output format: Print the points in sorted order. That is, sort the points by x coordinates in ascending order. If two points have the same x coordinate, the point with smaller y should be printed. If two points have the same x, and y coordinates, the point with smaller z should be printed.

Classes

Here is a list of classes you should implement. You can add more methods and data members to each of these classes or even add additional classes if necessary.

public class Point3D<T>
{
    public T position[3];
}
public class Range3D<T>
{
    public T min_x, max_x, min_y, max_y, min_z, max_z;
}
public class Node<T>
{
    public Node<T> left, right, next_level;
    public T data;
    public int dimension; //x:0, y:1, z:2
}
public class RangeTree<T>
{
      private Node< Point3D<T> > root;

      public void build( Point3D<T> [] points);

      public LinkedList< Point3D<T> > search(  Range3D<T> query );

      private Node< Point3D<T> > FindSplitNode( T min, T max);
}

Pseudo code

In general, it will be useful if you implement 1D range tree first, and then generalized it to 2D and then 3D.

Output format: Find split node Finding the split node for a given range for a given tree

Input: Two values x and x' with x <= x'
Output: The node v where the paths to x and x' splits, or the leaf where both paths end.

1. v <- root
2. while v is not a leaf and (x' <= xv or x > xv) {
3.     if x' <= xv
4.     then v <- lc(v) // left child of the node v 
5.     else v <- rc(v) // right child of the node v 
6. }
7. return v

1D Range Search

Input: A range tree T and a range [x:x']
Output: All points that lie in the range.

1. vsplit <- FindSplitNode(x, x')
2. if vsplit is a leaf
3. then Check if the point stored at vsplit must be reported
4. else // Follow the path to x and report the points in subtrees right of the path
5. v <- leftchild(vsplit)
6. while v is not a leaf
7. do if x <= xv
8. then ReportSubTree(rc(v))
9. v <- lc(v)
10. else v <- rc(v)
11. Check if the point stored at leaf v must be reported
12. Similarly, follow the path to x'

Build 2D Range Tree

Input: A set P of points in the plane.
Output: The root of 2-dimensional tree.

1. if P contains only 1 point
2.     then Create a leaf v storing this point and make T the associated structure of v.
3. else Split P into 2 subsets: 
            P_left containing points with x-coordinate <= x_mid, the median x-coordinate, and 
            P_right containing points with x-coordinate >= x_mid
4. vleft <- Build2DRangeTree(Pleft)
5. vright <- Build2DRangeTree(Pright)
6. Create a node v storing xmid, make vleft left child of v & vright right child of v, and make T the associated structure of v
7. v.next_level = a binary search tree T buily on the set Py of y-coordinates of the points in P.  
    Store at leaves of T the points themselves.
8. return v

Build 3D Range Tree

Build3DRangeTree

Input: A set P of points in the plane and current dimension D
Output: The root of range tree

1. if P contains only 1 point
2.     then Create a leaf v storing this point
        return v
3. else Split P into 2 subsets: 
            mid =  the median D-coordinate of P, where D=0 (x), 1 (y), or 2 (z)
            P_left containing points with D-coordinate <= mid
            P_right containing points with D-coordinate > mid
4. Create a node v storing mid
5. v.left = Build3DRangeTree(Pleft, D)
6. v.right = Build3DRangeTree(Pright, D)
7. if(D<2) v.next_level = Build2DRangeTree(P, D+1)
8. return v

3D Range Search

search

Input: A range R=[x:x', y:y', z:z']
Output: All points that lie in the range.

1. vsplit = FindSplitNode(R)
2. if vsplit is a leaf 
3. then Check if the point stored at vsplit must be reported
4. else { // Follow the path to x and report the points in subtrees right of the path
5.   v = vsplit.left

6.  while(v is not a leaf) do {
7.     if R[D*2] <= v.position[D]{ //R[D*2] is the lower bound of dimension D
8.        if(D==2) ReportSubTree(v.right) //Z tree
9.        else if(v.right is not a leaf) { v.right.next_level.search(R) }
           else Check if the point stored at leaf v.right must be reported 
10.      v = v.left }
11. else{ v = v.right} } //end while

12. Check if the point stored at leaf v must be reported
13. v = vsplit.right

14. while(v is not a leaf) do{
15.   if R[D*2+1] >= v.position[D]{ //R[D*2+1] is the upper bound of dimension D
16.      if(D==2) ReportSubTree(v.left) //Z tree
17.      else if(v.left is not a leaf) v.left.next_level.search(R)
           else Check if the point stored at leaf v.left must be reported 
18.      v= v.right}
19.   else{ v = v.left } } //end while

20. Check if the point stored at leaf v must be reported
21. }//end if/else

To hand in

You will submit on blackboard.

  • Your submission should include your (well organized and well commented) source code
  • Complete README.txt
  • You should include both source code and a binary called "310pa3.jar".
  • A terminal session showing you running your program with sample input that will be posted on this website
  • Your should zip all the files in a file called "PA3.Firstname.Lastname.zip"
  • Your TAs should be able to run your program by typing: "java -jar 310pa3.jar"

Rubrics

  • Implement all necessary input/output mechanism (10 points)
  • Build a range tree from an array of points (40 points)
  • Implement range search (40 points)
  • README.txt (5 points)
  • Code organization/comments (5 points)
  • Total point: 100