Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libTopology / src / org / gvsig / spatialindex / b2dtree / PriorityQueue.java @ 21250

History | View | Annotate | Download (7.99 KB)

1
package org.gvsig.spatialindex.b2dtree;
2
class PriorityQueue implements java.io.Serializable {
3

    
4
   /**
5
    * This class implements a <code>PriorityQueue</code>. This class
6
    * is implemented in such a way that objects are added using an
7
    * <code>add</code> function. The <code>add</code> function takes
8
    * two parameters an object and a long.
9
    * <p>
10
    * The object represents an item in the queue, the long indicates
11
    * its priority in the queue. The remove function in this class
12
    * returns the object first in the queue and that object is removed
13
    * from the queue permanently.
14
    *
15
    * @author  Bjoern Heckel
16
    * @version %I%, %G%
17
    * @since JDK1.2 
18
    */
19

    
20
   /**
21
    * The maximum priority possible in this priority queue.
22
    */
23
   private double maxPriority = Double.MAX_VALUE;
24

    
25
   /**
26
    * This contains the list of objects in the queue.
27
    */
28
   private Object[] data;
29

    
30
   /**
31
    * This contains the list of prioritys in the queue.
32
    */
33
   private double[] value;
34

    
35
   /**
36
    * Holds the number of elements currently in the queue.
37
    */
38
   private int count;
39

    
40
   /**
41
    * This holds the number elements this queue can have.
42
    */
43
   private int capacity;
44

    
45
   /**
46
    * Creates a new <code>PriorityQueue</code> object. The
47
    * <code>PriorityQueue</code> object allows objects to be
48
    * entered into the queue and to leave in the order of
49
    * priority i.e the highest priority get's to leave first.
50
    */
51
   public PriorityQueue() {
52
       init(20);
53
   }
54

    
55
   /**
56
    * Creates a new <code>PriorityQueue</code> object. The
57
    * <code>PriorityQueue</code> object allows objects to
58
    * be entered into the queue an to leave in the order of
59
    * priority i.e the highest priority get's to leave first.
60
    *
61
    * @param capacity the initial capacity of the queue before
62
    * a resize
63
    */
64
   public PriorityQueue(int capacity) {
65
       init(capacity);
66
   }
67

    
68
   /**
69
    * Creates a new <code>PriorityQueue</code> object. The
70
    * <code>PriorityQueue</code> object allows objects to
71
    * be entered into the queue an to leave in the order of
72
    * priority i.e the highest priority get's to leave first.
73
    *
74
    * @param capacity the initial capacity of the queue before
75
    * a resize
76
    * @param maxPriority is the maximum possible priority for
77
    * an object
78
    */
79
   public PriorityQueue(int capacity, double maxPriority) {
80
       this.maxPriority = maxPriority;
81
       init(capacity);
82
   }
83

    
84
   /**
85
    * This is an initializer for the object. It basically initializes
86
    * an array of long called value to represent the prioritys of
87
    * the objects, it also creates an array of objects to be used
88
    * in parallel with the array of longs, to represent the objects
89
    * entered, these can be used to sequence the data.
90
    *
91
    * @param size the initial capacity of the queue, it can be
92
    * resized
93
    */
94
   private void init(int size) {
95
       capacity = size;
96
       data = new Object[capacity + 1];
97
       value = new double[capacity + 1];
98
       value[0] = maxPriority;
99
       data[0] = null;
100
   }
101

    
102
   /**
103
    * This function adds the given object into the <code>PriorityQueue</code>,
104
    * its priority is the long priority. The way in which priority can be
105
    * associated with the elements of the queue is by keeping the priority
106
    * and the elements array entrys parallel.
107
    *
108
    * @param element is the object that is to be entered into this
109
    * <code>PriorityQueue</code>
110
    * @param priority this is the priority that the object holds in the
111
    * <code>PriorityQueue</code>
112
    */
113
   public void add(Object element, double priority) {
114
       if (count++ >= capacity) {
115
           expandCapacity();
116
       }
117
       /* put this as the last element */
118
       value[count] = priority;
119
       data[count] = element;
120
       bubbleUp(count);
121
   }
122

    
123
   /**
124
    * Remove is a function to remove the element in the queue with the
125
    * maximum priority. Once the element is removed then it can never be
126
    * recovered from the queue with further calls. The lowest priority
127
    * object will leave last.
128
    *
129
    * @return the object with the highest priority or if it's empty
130
    * null
131
    */
132
   public Object remove() {
133
       if (count == 0)
134
           return null;
135
       Object element = data[1];
136
       /* swap the last element into the first */
137
       data[1] = data[count];
138
       value[1] = value[count];
139
       /* let the GC clean up */
140
       data[count] = null;
141
       value[count] = 0L;
142
       count--;
143
       bubbleDown(1);
144
       return element;
145
   }
146

    
147
   public Object front() {
148
       return data[1];
149
   }
150

    
151
   public double getMaxPriority() {
152
       return value[1];
153
   }
154

    
155
   /**
156
    * Bubble down is used to put the element at subscript 'pos' into
157
    * it's rightful place in the heap (i.e heap is another name
158
    * for <code>PriorityQueue</code>). If the priority of an element
159
    * at subscript 'pos' is less than it's children then it must
160
    * be put under one of these children, i.e the ones with the
161
    * maximum priority must come first.
162
    *
163
    * @param pos is the position within the arrays of the element
164
    * and priority
165
    */
166
   private void bubbleDown(int pos) {
167
       Object element = data[pos];
168
       double priority = value[pos];
169
       int child;
170
       /* hole is position '1' */
171
       for (; pos * 2 <= count; pos = child) {
172
           child = pos * 2;
173
           /* if 'child' equals 'count' then there
174
              is only one leaf for this parent */
175
           if (child != count)
176

    
177
               /* left_child > right_child */
178
               if (value[child] < value[child + 1])
179
                   child++; /* choose the biggest child */
180
                   /* percolate down the data at 'pos', one level
181
                      i.e biggest child becomes the parent */
182
           if (priority < value[child]) {
183
               value[pos] = value[child];
184
               data[pos] = data[child];
185
           }
186
           else {
187
               break;
188
           }
189
       }
190
       value[pos] = priority;
191
       data[pos] = element;
192
   }
193

    
194
   /**
195
    * Bubble up is used to place an element relatively low in the
196
    * queue to it's rightful place higher in the queue, but only
197
    * if it's priority allows it to do so, similar to bubbleDown
198
    * only in the other direction this swaps out its parents.
199
    *
200
    * @param pos the position in the arrays of the object
201
    * to be bubbled up
202
    */
203
   private void bubbleUp(int pos) {
204
       Object element = data[pos];
205
       double priority = value[pos];
206
       /* when the parent is not less than the child, end*/
207
       while (value[pos / 2] < priority) {
208
           /* overwrite the child with the parent */
209
           value[pos] = value[pos / 2];
210
           data[pos] = data[pos / 2];
211
           pos /= 2;
212
       }
213
       value[pos] = priority;
214
       data[pos] = element;
215
   }
216

    
217
   /**
218
    * This ensures that there is enough space to keep adding elements
219
    * to the priority queue. It is however advised to make the capacity
220
    * of the queue large enough so that this will not be used as it is
221
    * an expensive method. This will copy across from 0 as 'off' equals
222
    * 0 is contains some important data.
223
    */
224
   private void expandCapacity() {
225
       capacity = count * 2;
226
       Object[] elements = new Object[capacity + 1];
227
       double[] prioritys = new double[capacity + 1];
228
       System.arraycopy(data, 0, elements, 0, data.length);
229
       System.arraycopy(value, 0, prioritys, 0, data.length);
230
       data = elements;
231
       value = prioritys;
232
   }
233

    
234
   /**
235
    * This method will empty the queue. This also helps garbage
236
    * collection by releasing any reference it has to the elements
237
    * in the queue. This starts from offset 1 as off equals 0
238
    * for the elements array.
239
    */
240
   public void clear() {
241
       for (int i = 1; i < count; i++) {
242
           data[i] = null; /* help gc */
243
       }
244
       count = 0;
245
   }
246

    
247
   /**
248
    * The number of elements in the queue. The length
249
    * indicates the number of elements that are currently
250
    * in the queue.
251
    *
252
    * @return the number of elements in the queue
253
    */
254
   public int length() {
255
       return count;
256
   }
257
}