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 |
} |