PA 003
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