高级数据库的大作业,水过,代码写的不是很好,主要是处理I/O这块,没有找到更好的办法,时间问题,所以只能妥协了

可能我做的这个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 

一维间距
 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  }

二维间距
 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  }

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  }

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