高级数据库的大作业,水过,代码写的不是很好,主要是处理I/O这块,没有找到更好的办法,时间问题,所以只能妥协了
可能我做的这个Quadtree比较奇怪,具体的可以参考UMD的那个Spatial Demo
网址如下:http://donar.umiacs.umd.edu/quadtree/
贴一下代码好了,有需要的人可以跟我一起讨论,以后如果有机会会改进这个代码的
IO操作类
一维间距
二维间距
Quadtree
JUnit 测试类
可能我做的这个Quadtree比较奇怪,具体的可以参考UMD的那个Spatial Demo
网址如下:http://donar.umiacs.umd.edu/quadtree/
贴一下代码好了,有需要的人可以跟我一起讨论,以后如果有机会会改进这个代码的
IO操作类
1
import
java.io.
*
;
2 import java.util.ArrayList;
3
4 /*
5 * This is a helper class
6 * used to support file operation
7 */
8 public class FileOperator {
9
10 // Input Stream
11 FileInputStream fis;
12 FileOutputStream fos;
13
14 // Output Stream
15 ObjectInputStream ois;
16 ObjectOutputStream oos;
17
18 String filename;
19
20 public FileOperator(String filename)
21 {
22 this .filename = filename;
23 }
24
25 /*
26 * Get the entry in the position
27 */
28 public Object getObjectAt( long position)
29 {
30 int count = 0 ;
31 try
32 {
33 fis = new FileInputStream(filename);
34 ois = new ObjectInputStream(fis);
35
36 Object temp = ois.readObject();
37 while (count < position)
38 {
39 temp = ois.readObject();
40 count ++ ;
41 }
42 return temp;
43 }
44 catch (Exception e)
45 {
46 e.printStackTrace();
47 }
48
49 // Close the stream
50 try {
51 fis.close();
52 ois.close();
53 } catch (IOException e) {
54 // TODO Auto-generated catch block
55 e.printStackTrace();
56 }
57 return null ;
58 }
59
60 /*
61 * Append a new object into the file
62 * just follow the last entry
63 */
64 public void appendObject(Object addin)
65 {
66 ArrayList < Object > arrayList = new ArrayList < Object > ();
67 try {
68 fis = new FileInputStream(filename);
69 ois = new ObjectInputStream(fis);
70
71 Object temp;
72 do
73 {
74 temp = ois.readObject();
75 arrayList.add(temp);
76 }
77 while (temp != null );
78
79 } catch (Exception e) {
80 }
81 // Close the file
82 try {
83 fis.close();
84 ois.close();
85 } catch (Exception e) {
86 }
87
88 // Add the new object into the file
89 try {
90 fos = new FileOutputStream(filename);
91 oos = new ObjectOutputStream(fos);
92 for (Object i : arrayList)
93 {
94 oos.writeObject(i);
95 }
96 oos.writeObject(addin);
97 } catch (IOException e) {
98 // TODO Auto-generated catch block
99 e.printStackTrace();
100 }
101
102 // Close the file
103 try {
104 fos.close();
105 oos.close();
106 } catch (Exception e) {
107 e.printStackTrace();
108 }
109 }
110
111 /*
112 * List the content of the file
113 * print the object using the toString method
114 */
115 public long fileContent()
116 {
117 long count = 0 ;
118 try {
119 fis = new FileInputStream(filename);
120 ois = new ObjectInputStream(fis);
121
122 Object temp;
123 do
124 {
125 temp = ois.readObject();
126 count ++ ;
127 // System.out.println(temp.toString());
128 }
129 while (temp != null );
130 } catch (Exception e) {
131 }
132 return count;
133 }
134 }
135
2 import java.util.ArrayList;
3
4 /*
5 * This is a helper class
6 * used to support file operation
7 */
8 public class FileOperator {
9
10 // Input Stream
11 FileInputStream fis;
12 FileOutputStream fos;
13
14 // Output Stream
15 ObjectInputStream ois;
16 ObjectOutputStream oos;
17
18 String filename;
19
20 public FileOperator(String filename)
21 {
22 this .filename = filename;
23 }
24
25 /*
26 * Get the entry in the position
27 */
28 public Object getObjectAt( long position)
29 {
30 int count = 0 ;
31 try
32 {
33 fis = new FileInputStream(filename);
34 ois = new ObjectInputStream(fis);
35
36 Object temp = ois.readObject();
37 while (count < position)
38 {
39 temp = ois.readObject();
40 count ++ ;
41 }
42 return temp;
43 }
44 catch (Exception e)
45 {
46 e.printStackTrace();
47 }
48
49 // Close the stream
50 try {
51 fis.close();
52 ois.close();
53 } catch (IOException e) {
54 // TODO Auto-generated catch block
55 e.printStackTrace();
56 }
57 return null ;
58 }
59
60 /*
61 * Append a new object into the file
62 * just follow the last entry
63 */
64 public void appendObject(Object addin)
65 {
66 ArrayList < Object > arrayList = new ArrayList < Object > ();
67 try {
68 fis = new FileInputStream(filename);
69 ois = new ObjectInputStream(fis);
70
71 Object temp;
72 do
73 {
74 temp = ois.readObject();
75 arrayList.add(temp);
76 }
77 while (temp != null );
78
79 } catch (Exception e) {
80 }
81 // Close the file
82 try {
83 fis.close();
84 ois.close();
85 } catch (Exception e) {
86 }
87
88 // Add the new object into the file
89 try {
90 fos = new FileOutputStream(filename);
91 oos = new ObjectOutputStream(fos);
92 for (Object i : arrayList)
93 {
94 oos.writeObject(i);
95 }
96 oos.writeObject(addin);
97 } catch (IOException e) {
98 // TODO Auto-generated catch block
99 e.printStackTrace();
100 }
101
102 // Close the file
103 try {
104 fos.close();
105 oos.close();
106 } catch (Exception e) {
107 e.printStackTrace();
108 }
109 }
110
111 /*
112 * List the content of the file
113 * print the object using the toString method
114 */
115 public long fileContent()
116 {
117 long count = 0 ;
118 try {
119 fis = new FileInputStream(filename);
120 ois = new ObjectInputStream(fis);
121
122 Object temp;
123 do
124 {
125 temp = ois.readObject();
126 count ++ ;
127 // System.out.println(temp.toString());
128 }
129 while (temp != null );
130 } catch (Exception e) {
131 }
132 return count;
133 }
134 }
135
一维间距
1
/*
2 * This class is used to describe 1-D Space
3 */
4 public class Interval < Key extends Comparable > {
5 public final Key low; // left endpoint
6 public final Key high; // right endpoint
7
8 public Interval(Key low, Key high) {
9 if (less(high, low)) throw new RuntimeException( " Illegal argument " );
10 this .low = low;
11 this .high = high;
12 }
13
14 // is x between low and high
15 public boolean contains(Key x) {
16 return ! less(x, low) && ! less(high, x);
17 }
18
19 // does this interval intersect that interval?
20 public boolean intersects(Interval < Key > that) {
21 if (less( this .high, that.low)) return false ;
22 if (less(that.high, this .low)) return false ;
23 return true ;
24 }
25
26 // does this interval equal that interval?
27 public boolean equals(Interval < Key > that) {
28 return this .low.equals(that.low) && this .high.equals(that.high);
29 }
30
31
32 // comparison helper functions
33 private boolean less(Key x, Key y) {
34 return x.compareTo(y) < 0 ;
35 }
36
37 // return string representation
38 public String toString() {
39 return " [ " + low + " , " + high + " ] " ;
40 }
41 }
2 * This class is used to describe 1-D Space
3 */
4 public class Interval < Key extends Comparable > {
5 public final Key low; // left endpoint
6 public final Key high; // right endpoint
7
8 public Interval(Key low, Key high) {
9 if (less(high, low)) throw new RuntimeException( " Illegal argument " );
10 this .low = low;
11 this .high = high;
12 }
13
14 // is x between low and high
15 public boolean contains(Key x) {
16 return ! less(x, low) && ! less(high, x);
17 }
18
19 // does this interval intersect that interval?
20 public boolean intersects(Interval < Key > that) {
21 if (less( this .high, that.low)) return false ;
22 if (less(that.high, this .low)) return false ;
23 return true ;
24 }
25
26 // does this interval equal that interval?
27 public boolean equals(Interval < Key > that) {
28 return this .low.equals(that.low) && this .high.equals(that.high);
29 }
30
31
32 // comparison helper functions
33 private boolean less(Key x, Key y) {
34 return x.compareTo(y) < 0 ;
35 }
36
37 // return string representation
38 public String toString() {
39 return " [ " + low + " , " + high + " ] " ;
40 }
41 }
二维间距
1
/*
2 * This class is used to describe 2-D Space
3 */
4 public class Interval2D < Key extends Comparable > {
5 public final Interval < Key > intervalX; // x-interval
6 public final Interval < Key > intervalY; // y-interval
7
8 public Interval2D(Interval < Key > intervalX, Interval < Key > intervalY) {
9 this .intervalX = intervalX;
10 this .intervalY = intervalY;
11 }
12
13 // does this 2D interval a intersect b?
14 public boolean intersects(Interval2D < Key > b) {
15 if (intervalX.intersects(b.intervalX)) return true ;
16 if (intervalY.intersects(b.intervalY)) return true ;
17 return false ;
18 }
19
20 // does this 2D interval contain (x, y)?
21 public boolean contains(Key x, Key y) {
22 return intervalX.contains(x) && intervalY.contains(y);
23 }
24
25 // return string representation
26 public String toString() {
27 return intervalX + " x " + intervalY;
28 }
29 }
2 * This class is used to describe 2-D Space
3 */
4 public class Interval2D < Key extends Comparable > {
5 public final Interval < Key > intervalX; // x-interval
6 public final Interval < Key > intervalY; // y-interval
7
8 public Interval2D(Interval < Key > intervalX, Interval < Key > intervalY) {
9 this .intervalX = intervalX;
10 this .intervalY = intervalY;
11 }
12
13 // does this 2D interval a intersect b?
14 public boolean intersects(Interval2D < Key > b) {
15 if (intervalX.intersects(b.intervalX)) return true ;
16 if (intervalY.intersects(b.intervalY)) return true ;
17 return false ;
18 }
19
20 // does this 2D interval contain (x, y)?
21 public boolean contains(Key x, Key y) {
22 return intervalX.contains(x) && intervalY.contains(y);
23 }
24
25 // return string representation
26 public String toString() {
27 return intervalX + " x " + intervalY;
28 }
29 }
Quadtree
1
import
java.io.FileInputStream;
2 import java.io.FileOutputStream;
3 import java.io.ObjectInputStream;
4 import java.io.ObjectOutputStream;
5 import java.io.Serializable;
6 import java.util. * ;
7 /*
8 * The Quadtree built in this class is Point-Quadtree
9 * |
10 * SW | SE
11 * |
12 * -------------------
13 * |
14 * NW | NE
15 * |
16 */
17 public class QuadTree < Key extends Comparable, Value > implements Serializable {
18
19 private static final long serialVersionUID = 2478226174742279217L ;
20 // The root of the quadtree, the variable here is to represent the whole quadtree
21 private Node root;
22 // The page size as required
23 public static int PageSize = 4 ;
24
25 private ArrayList < IndexEntry > pointarray;
26
27 private long pointposition = - 1 ;
28
29 public static long dataID = 0 ;
30
31 // The data class type
32 private class IndexEntry implements Serializable{
33 private static final long serialVersionUID = 5520800067960787705L ;
34 Key x,y;
35 long id;
36
37 public IndexEntry(Key x, Key y, long id) {
38 // TODO Auto-generated constructor stub
39 this .x = x;
40 this .y = y;
41 this .id = id;
42 }
43
44 public boolean equals(IndexEntry that)
45 {
46 if ( this .x.equals(that.x) && this .y.equals( this .y) && this .id == that.id)
47 return true ;
48 else
49 return false ;
50 }
51 }
52
53 // helper node data type
54 private class Node implements Serializable{
55
56 private static final long serialVersionUID = 5226775272372026596L ;
57 // A node contains a few data entries
58 ArrayList < IndexEntry > indexArrayList;
59 int DataCount;
60 private boolean split;
61 // If the node has been split, then it should contain 4 branches
62 Node NW, NE, SE, SW; // four subtrees
63
64
65 // The value that belongs to the node
66 // and we use this x,y as a standard to dispatch other nodes
67 Key x,y;
68 long id;
69
70 // Constructor
71 Node() {
72 indexArrayList = new ArrayList < IndexEntry > (PageSize);
73 DataCount = 0 ;
74 split = false ;
75 }
76
77 public boolean isSplit()
78 {
79 return split;
80 }
81
82 public void setSplit()
83 {
84 split = true ;
85 }
86
87 public void assignvalue(IndexEntry input)
88 {
89 this .x = input.x;
90 this .y = input.y;
91 this .id = input.id;
92 }
93 }
94
95
96 public QuadTree()
97 {
98 importIndex();
99 }
100
101 public void exportIndex()
102 {
103 ObjectOutputStream out;
104 try {
105 out = new ObjectOutputStream( new FileOutputStream( " index.dat " ));
106 out.writeObject(root);
107 out.close();
108 }
109 catch (Exception e){
110 e.printStackTrace();
111 }
112 }
113
114 public void importIndex()
115 {
116 ObjectInputStream in;
117 try
118 {
119 in = new ObjectInputStream( new FileInputStream( " index.dat " ));
120 root = (Node) in.readObject();
121 in.close();
122 }
123 catch (Exception e){
124 e.printStackTrace();
125 }
126 }
127 /** *********************************************************************
128 * Insert (x, y) into appropriate quadrant
129 ********************************************************************** */
130 public void insert(Key x, Key y, Value value) {
131
132 // found the number of the data entries
133 FileOperator fo = new FileOperator( " data.dat " );
134 dataID = fo.fileContent();
135
136 // Insert
137 root = insert(root, x, y, dataID);
138
139 exportIndex();
140
141 // update the data file
142 fo.appendObject(value);
143 }
144
145 private Node insert(Node h, Key x, Key y, long ID) {
146 // if there is a slot for the value, then insert it
147
148 if (h == null )
149 {
150 Node tempnode = new Node();
151 IndexEntry tempdata = new IndexEntry(x,y,ID);
152 tempnode.indexArrayList.add(tempdata);
153 tempnode.DataCount ++ ;
154 return tempnode;
155 }
156 else
157 {
158 if (h.isSplit())
159 {
160 if ( less(x, h.x) && less(y, h.y)) h.SW = insert(h.SW, x, y, ID);
161 else if ( less(x, h.x) && ! less(y, h.y)) h.NW = insert(h.NW, x, y, ID);
162 else if ( ! less(x, h.x) && less(y, h.y)) h.SE = insert(h.SE, x, y, ID);
163 else if ( ! less(x, h.x) && ! less(y, h.y)) h.NE = insert(h.NE, x, y, ID);
164 }
165 else
166 {
167 if (h.DataCount < PageSize)
168 {
169 // create an object containing the value
170 IndexEntry tempDataEntry = new IndexEntry(x,y,ID);
171 // put the new object into the node
172 h.indexArrayList.add(tempDataEntry);
173 // count number ++
174 h.DataCount ++ ;
175 }
176 // need to split
177 else
178 {
179 // Set the standard
180 IndexEntry temp = new IndexEntry(x,y,ID);
181 h.assignvalue(temp);
182
183 // Mark the flag that the node has already been split
184 h.setSplit();
185
186 for (IndexEntry i: h.indexArrayList)
187 {
188 if ( less(i.x, h.x) && less(i.y, h.y)) h.SW = insert(h.SW, i.x, i.y, i.id);
189 else if ( less(i.x, h.x) && ! less(i.y, h.y)) h.NW = insert(h.NW, i.x, i.y, i.id);
190 else if ( ! less(i.x, h.x) && less(i.y, h.y)) h.SE = insert(h.SE, i.x, i.y, i.id);
191 else if ( ! less(i.x, h.x) && ! less(i.y, h.y)) h.NE = insert(h.NE, i.x, i.y, i.id);
192 }
193
194 // Clear the data array
195 h.indexArrayList.clear();
196 h.DataCount = 0 ;
197 }
198 }
199 return h;
200 }
201 }
202
203 /** *********************************************************************
204 * Point search.
205 ********************************************************************** */
206 public void queryPoint(Key x, Key y)
207 {
208
209 long position = queryPoint(root,x,y);
210
211 FileOperator fo = new FileOperator( " data.dat " );
212
213 System.out.println( " ******************************** " );
214 System.out.println(position);
215 System.out.println( " The value at ( " + x + " , " + y + " ) is " + fo.getObjectAt(position).toString());
216 System.out.println( " ******************************** " );
217 }
218
219 private long queryPoint(Node h, Key x, Key y)
220 {
221 // the base condition
222 if (h == null ) return - 1 ;
223 // found the value
224 if (h.isSplit())
225 {
226 if (h.x.equals(x) && h.y.equals(y))
227 {
228 System.out.println(h.id);
229 pointposition = h.id;
230 }
231 else if ( less(x, h.x) && less(y, h.y)) queryPoint(h.SW, x,y);
232 else if ( less(x, h.x) && ! less(y, h.y)) queryPoint(h.NW, x,y);
233 else if ( ! less(x, h.x) && less(y, h.y)) queryPoint(h.SE, x,y);
234 else if ( ! less(x, h.x) && ! less(y, h.y)) queryPoint(h.NE, x,y);
235 }
236 else {
237 for (IndexEntry i: h.indexArrayList)
238 {
239 if (i.x.equals(x) && i.y.equals(y))
240 {
241 System.out.println(i.id);
242 pointposition = i.id;
243 }
244 }
245 }
246 return pointposition;
247 }
248
249 /** *********************************************************************
250 * Range search.
251 ********************************************************************** */
252
253 public void query2D(Interval2D < Key > rect) {
254 pointarray = new ArrayList < IndexEntry > ();
255 query2D(root, rect);
256
257 FileOperator fo = new FileOperator( " data.dat " );
258
259 System.out.println( " ******************************** " );
260
261 for (IndexEntry i: pointarray)
262 {
263 System.out.println( " The value at ( " + i.x + " , " + i.y + " ) is " + fo.getObjectAt(i.id).toString());
264 }
265 System.out.println( " ******************************** " );
266 }
267
268 private void query2D(Node h, Interval2D < Key > rect) {
269 if (h == null ) return ;
270 Key xmin = rect.intervalX.low;
271 Key ymin = rect.intervalY.low;
272 Key xmax = rect.intervalX.high;
273 Key ymax = rect.intervalY.high;
274
275 // found one
276 if (h.isSplit())
277 {
278 if (rect.contains(h.x, h.y))
279 {
280 // System.out.println(" (" + h.x + ", " + h.y + ") " + h.id);
281 pointarray.add( new IndexEntry(h.x,h.y,h.id));
282 }
283
284 // search the points in the four partitions
285 if ( less(xmin, h.x) && less(ymin, h.y)) query2D(h.SW, rect);
286 if ( less(xmin, h.x) && ! less(ymax, h.y)) query2D(h.NW, rect);
287 if ( ! less(xmax, h.x) && less(ymin, h.y)) query2D(h.SE, rect);
288 if ( ! less(xmax, h.x) && ! less(ymax, h.y)) query2D(h.NE, rect);
289 }
290 else
291 {
292 for (IndexEntry i: h.indexArrayList)
293 {
294 if (rect.contains(i.x, i.y))
295 {
296 // System.out.println(" (" + i.x + ", " + i.y + ") " + i.id);
297 pointarray.add(i);
298 }
299 }
300 }
301 }
302
303
304 /** ***********************************************************************
305 * helper comparison functions
306 ************************************************************************ */
307
308 private boolean less(Key k1, Key k2) { return k1.compareTo(k2) < 0 ; }
309 private boolean eq (Key k1, Key k2) { return k1.compareTo(k2) == 0 ; }
310 }
2 import java.io.FileOutputStream;
3 import java.io.ObjectInputStream;
4 import java.io.ObjectOutputStream;
5 import java.io.Serializable;
6 import java.util. * ;
7 /*
8 * The Quadtree built in this class is Point-Quadtree
9 * |
10 * SW | SE
11 * |
12 * -------------------
13 * |
14 * NW | NE
15 * |
16 */
17 public class QuadTree < Key extends Comparable, Value > implements Serializable {
18
19 private static final long serialVersionUID = 2478226174742279217L ;
20 // The root of the quadtree, the variable here is to represent the whole quadtree
21 private Node root;
22 // The page size as required
23 public static int PageSize = 4 ;
24
25 private ArrayList < IndexEntry > pointarray;
26
27 private long pointposition = - 1 ;
28
29 public static long dataID = 0 ;
30
31 // The data class type
32 private class IndexEntry implements Serializable{
33 private static final long serialVersionUID = 5520800067960787705L ;
34 Key x,y;
35 long id;
36
37 public IndexEntry(Key x, Key y, long id) {
38 // TODO Auto-generated constructor stub
39 this .x = x;
40 this .y = y;
41 this .id = id;
42 }
43
44 public boolean equals(IndexEntry that)
45 {
46 if ( this .x.equals(that.x) && this .y.equals( this .y) && this .id == that.id)
47 return true ;
48 else
49 return false ;
50 }
51 }
52
53 // helper node data type
54 private class Node implements Serializable{
55
56 private static final long serialVersionUID = 5226775272372026596L ;
57 // A node contains a few data entries
58 ArrayList < IndexEntry > indexArrayList;
59 int DataCount;
60 private boolean split;
61 // If the node has been split, then it should contain 4 branches
62 Node NW, NE, SE, SW; // four subtrees
63
64
65 // The value that belongs to the node
66 // and we use this x,y as a standard to dispatch other nodes
67 Key x,y;
68 long id;
69
70 // Constructor
71 Node() {
72 indexArrayList = new ArrayList < IndexEntry > (PageSize);
73 DataCount = 0 ;
74 split = false ;
75 }
76
77 public boolean isSplit()
78 {
79 return split;
80 }
81
82 public void setSplit()
83 {
84 split = true ;
85 }
86
87 public void assignvalue(IndexEntry input)
88 {
89 this .x = input.x;
90 this .y = input.y;
91 this .id = input.id;
92 }
93 }
94
95
96 public QuadTree()
97 {
98 importIndex();
99 }
100
101 public void exportIndex()
102 {
103 ObjectOutputStream out;
104 try {
105 out = new ObjectOutputStream( new FileOutputStream( " index.dat " ));
106 out.writeObject(root);
107 out.close();
108 }
109 catch (Exception e){
110 e.printStackTrace();
111 }
112 }
113
114 public void importIndex()
115 {
116 ObjectInputStream in;
117 try
118 {
119 in = new ObjectInputStream( new FileInputStream( " index.dat " ));
120 root = (Node) in.readObject();
121 in.close();
122 }
123 catch (Exception e){
124 e.printStackTrace();
125 }
126 }
127 /** *********************************************************************
128 * Insert (x, y) into appropriate quadrant
129 ********************************************************************** */
130 public void insert(Key x, Key y, Value value) {
131
132 // found the number of the data entries
133 FileOperator fo = new FileOperator( " data.dat " );
134 dataID = fo.fileContent();
135
136 // Insert
137 root = insert(root, x, y, dataID);
138
139 exportIndex();
140
141 // update the data file
142 fo.appendObject(value);
143 }
144
145 private Node insert(Node h, Key x, Key y, long ID) {
146 // if there is a slot for the value, then insert it
147
148 if (h == null )
149 {
150 Node tempnode = new Node();
151 IndexEntry tempdata = new IndexEntry(x,y,ID);
152 tempnode.indexArrayList.add(tempdata);
153 tempnode.DataCount ++ ;
154 return tempnode;
155 }
156 else
157 {
158 if (h.isSplit())
159 {
160 if ( less(x, h.x) && less(y, h.y)) h.SW = insert(h.SW, x, y, ID);
161 else if ( less(x, h.x) && ! less(y, h.y)) h.NW = insert(h.NW, x, y, ID);
162 else if ( ! less(x, h.x) && less(y, h.y)) h.SE = insert(h.SE, x, y, ID);
163 else if ( ! less(x, h.x) && ! less(y, h.y)) h.NE = insert(h.NE, x, y, ID);
164 }
165 else
166 {
167 if (h.DataCount < PageSize)
168 {
169 // create an object containing the value
170 IndexEntry tempDataEntry = new IndexEntry(x,y,ID);
171 // put the new object into the node
172 h.indexArrayList.add(tempDataEntry);
173 // count number ++
174 h.DataCount ++ ;
175 }
176 // need to split
177 else
178 {
179 // Set the standard
180 IndexEntry temp = new IndexEntry(x,y,ID);
181 h.assignvalue(temp);
182
183 // Mark the flag that the node has already been split
184 h.setSplit();
185
186 for (IndexEntry i: h.indexArrayList)
187 {
188 if ( less(i.x, h.x) && less(i.y, h.y)) h.SW = insert(h.SW, i.x, i.y, i.id);
189 else if ( less(i.x, h.x) && ! less(i.y, h.y)) h.NW = insert(h.NW, i.x, i.y, i.id);
190 else if ( ! less(i.x, h.x) && less(i.y, h.y)) h.SE = insert(h.SE, i.x, i.y, i.id);
191 else if ( ! less(i.x, h.x) && ! less(i.y, h.y)) h.NE = insert(h.NE, i.x, i.y, i.id);
192 }
193
194 // Clear the data array
195 h.indexArrayList.clear();
196 h.DataCount = 0 ;
197 }
198 }
199 return h;
200 }
201 }
202
203 /** *********************************************************************
204 * Point search.
205 ********************************************************************** */
206 public void queryPoint(Key x, Key y)
207 {
208
209 long position = queryPoint(root,x,y);
210
211 FileOperator fo = new FileOperator( " data.dat " );
212
213 System.out.println( " ******************************** " );
214 System.out.println(position);
215 System.out.println( " The value at ( " + x + " , " + y + " ) is " + fo.getObjectAt(position).toString());
216 System.out.println( " ******************************** " );
217 }
218
219 private long queryPoint(Node h, Key x, Key y)
220 {
221 // the base condition
222 if (h == null ) return - 1 ;
223 // found the value
224 if (h.isSplit())
225 {
226 if (h.x.equals(x) && h.y.equals(y))
227 {
228 System.out.println(h.id);
229 pointposition = h.id;
230 }
231 else if ( less(x, h.x) && less(y, h.y)) queryPoint(h.SW, x,y);
232 else if ( less(x, h.x) && ! less(y, h.y)) queryPoint(h.NW, x,y);
233 else if ( ! less(x, h.x) && less(y, h.y)) queryPoint(h.SE, x,y);
234 else if ( ! less(x, h.x) && ! less(y, h.y)) queryPoint(h.NE, x,y);
235 }
236 else {
237 for (IndexEntry i: h.indexArrayList)
238 {
239 if (i.x.equals(x) && i.y.equals(y))
240 {
241 System.out.println(i.id);
242 pointposition = i.id;
243 }
244 }
245 }
246 return pointposition;
247 }
248
249 /** *********************************************************************
250 * Range search.
251 ********************************************************************** */
252
253 public void query2D(Interval2D < Key > rect) {
254 pointarray = new ArrayList < IndexEntry > ();
255 query2D(root, rect);
256
257 FileOperator fo = new FileOperator( " data.dat " );
258
259 System.out.println( " ******************************** " );
260
261 for (IndexEntry i: pointarray)
262 {
263 System.out.println( " The value at ( " + i.x + " , " + i.y + " ) is " + fo.getObjectAt(i.id).toString());
264 }
265 System.out.println( " ******************************** " );
266 }
267
268 private void query2D(Node h, Interval2D < Key > rect) {
269 if (h == null ) return ;
270 Key xmin = rect.intervalX.low;
271 Key ymin = rect.intervalY.low;
272 Key xmax = rect.intervalX.high;
273 Key ymax = rect.intervalY.high;
274
275 // found one
276 if (h.isSplit())
277 {
278 if (rect.contains(h.x, h.y))
279 {
280 // System.out.println(" (" + h.x + ", " + h.y + ") " + h.id);
281 pointarray.add( new IndexEntry(h.x,h.y,h.id));
282 }
283
284 // search the points in the four partitions
285 if ( less(xmin, h.x) && less(ymin, h.y)) query2D(h.SW, rect);
286 if ( less(xmin, h.x) && ! less(ymax, h.y)) query2D(h.NW, rect);
287 if ( ! less(xmax, h.x) && less(ymin, h.y)) query2D(h.SE, rect);
288 if ( ! less(xmax, h.x) && ! less(ymax, h.y)) query2D(h.NE, rect);
289 }
290 else
291 {
292 for (IndexEntry i: h.indexArrayList)
293 {
294 if (rect.contains(i.x, i.y))
295 {
296 // System.out.println(" (" + i.x + ", " + i.y + ") " + i.id);
297 pointarray.add(i);
298 }
299 }
300 }
301 }
302
303
304 /** ***********************************************************************
305 * helper comparison functions
306 ************************************************************************ */
307
308 private boolean less(Key k1, Key k2) { return k1.compareTo(k2) < 0 ; }
309 private boolean eq (Key k1, Key k2) { return k1.compareTo(k2) == 0 ; }
310 }
JUnit 测试类
1
import
java.io.IOException;
2
3 import junit.framework.TestCase;
4
5
6 public class QuadTreeTest extends TestCase {
7 QuadTree < Integer, String > qt;
8
9 protected void setUp() throws Exception {
10 super .setUp();
11 }
12
13 protected void tearDown() throws Exception {
14 super .tearDown();
15 }
16
17 public void testInsert() throws IOException {
18 qt = new QuadTree < Integer, String > ();
19 for ( int i = 0 ; i < 20 ; i ++ )
20 for ( int j = 0 ; j < 20 ; j ++ )
21 {
22 qt.insert(i, j, " Point " + i + j);
23 }
24 }
25
26 public void testQueryPoint() throws IOException {
27 qt = new QuadTree < Integer, String > ();
28
29 for ( int i = 0 ; i < 20 ; i ++ )
30 for ( int j = 0 ; j < 20 ; j ++ )
31 {
32 qt.queryPoint(i * 2 ,j * 2 );
33 }
34 }
35
36 public void testQuery2D() throws IOException {
37 qt = new QuadTree < Integer, String > ();
38
39 for ( int i = 0 ; i < 1000 ; i ++ )
40 {
41 Integer xmin = ( int ) ( 20 * Math.random());
42 Integer ymin = ( int ) ( 20 * Math.random());
43 Integer xmax = xmin + ( int ) ( 10 * Math.random());
44 Integer ymax = ymin + ( int ) ( 10 * Math.random());
45 Interval < Integer > intX = new Interval < Integer > (xmin, xmax);
46 Interval < Integer > intY = new Interval < Integer > (ymin, ymax);
47 Interval2D < Integer > rect = new Interval2D < Integer > (intX, intY);
48 qt.query2D(rect);
49 }
50 }
51
52 }
53
2
3 import junit.framework.TestCase;
4
5
6 public class QuadTreeTest extends TestCase {
7 QuadTree < Integer, String > qt;
8
9 protected void setUp() throws Exception {
10 super .setUp();
11 }
12
13 protected void tearDown() throws Exception {
14 super .tearDown();
15 }
16
17 public void testInsert() throws IOException {
18 qt = new QuadTree < Integer, String > ();
19 for ( int i = 0 ; i < 20 ; i ++ )
20 for ( int j = 0 ; j < 20 ; j ++ )
21 {
22 qt.insert(i, j, " Point " + i + j);
23 }
24 }
25
26 public void testQueryPoint() throws IOException {
27 qt = new QuadTree < Integer, String > ();
28
29 for ( int i = 0 ; i < 20 ; i ++ )
30 for ( int j = 0 ; j < 20 ; j ++ )
31 {
32 qt.queryPoint(i * 2 ,j * 2 );
33 }
34 }
35
36 public void testQuery2D() throws IOException {
37 qt = new QuadTree < Integer, String > ();
38
39 for ( int i = 0 ; i < 1000 ; i ++ )
40 {
41 Integer xmin = ( int ) ( 20 * Math.random());
42 Integer ymin = ( int ) ( 20 * Math.random());
43 Integer xmax = xmin + ( int ) ( 10 * Math.random());
44 Integer ymax = ymin + ( int ) ( 10 * Math.random());
45 Interval < Integer > intX = new Interval < Integer > (xmin, xmax);
46 Interval < Integer > intY = new Interval < Integer > (ymin, ymax);
47 Interval2D < Integer > rect = new Interval2D < Integer > (intX, intY);
48 qt.query2D(rect);
49 }
50 }
51
52 }
53