ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/PriorityQueue.java
Revision: 1.22
Committed: Tue Aug 5 12:11:08 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.21: +128 -32 lines
Log Message:
Remove Sorted interface, adjust PQ and PBQ

File Contents

# Content
1 package java.util;
2
3 /**
4 * An unbounded priority queue based on a priority heap. This queue orders
5 * elements according to an order specified at construction time, which is
6 * specified in the same manner as {@link java.util.TreeSet} and
7 * {@link java.util.TreeMap}: elements are ordered
8 * either according to their <i>natural order</i> (see {@link Comparable}), or
9 * according to a {@link java.util.Comparator}, depending on which
10 * constructor is used.
11 * <p>The <em>head</em> of this queue is the <em>least</em> element with
12 * respect to the specified ordering.
13 * If multiple elements are tied for least value, the
14 * head is one of those elements. A priority queue does not permit
15 * <tt>null</tt> elements.
16 *
17 * <p>The {@link #remove()} and {@link #poll()} methods remove and
18 * return the head of the queue.
19 *
20 * <p>The {@link #element()} and {@link #peek()} methods return, but do
21 * not delete, the head of the queue.
22 *
23 * <p>A priority queue has a <i>capacity</i>. The capacity is the
24 * size of the array used internally to store the elements on the
25 * queue.
26 * It is always at least as large as the queue size. As
27 * elements are added to a priority queue, its capacity grows
28 * automatically. The details of the growth policy are not specified.
29 *
30 * <p>Implementation note: this implementation provides O(log(n)) time
31 * for the insertion methods (<tt>offer</tt>, <tt>poll</tt>,
32 * <tt>remove()</tt> and <tt>add</tt>) methods; linear time for the
33 * <tt>remove(Object)</tt> and <tt>contains(Object)</tt> methods; and
34 * constant time for the retrieval methods (<tt>peek</tt>,
35 * <tt>element</tt>, and <tt>size</tt>).
36 *
37 * <p>This class is a member of the
38 * <a href="{@docRoot}/../guide/collections/index.html">
39 * Java Collections Framework</a>.
40 * @since 1.5
41 * @author Josh Bloch
42 */
43 public class PriorityQueue<E> extends AbstractQueue<E>
44 implements Queue<E>, java.io.Serializable {
45
46 private static final int DEFAULT_INITIAL_CAPACITY = 11;
47
48 /**
49 * Priority queue represented as a balanced binary heap: the two children
50 * of queue[n] are queue[2*n] and queue[2*n + 1]. The priority queue is
51 * ordered by comparator, or by the elements' natural ordering, if
52 * comparator is null: For each node n in the heap and each descendant d
53 * of n, n <= d.
54 *
55 * The element with the lowest value is in queue[1], assuming the queue is
56 * nonempty. (A one-based array is used in preference to the traditional
57 * zero-based array to simplify parent and child calculations.)
58 *
59 * queue.length must be >= 2, even if size == 0.
60 */
61 private transient Object[] queue;
62
63 /**
64 * The number of elements in the priority queue.
65 */
66 private int size = 0;
67
68 /**
69 * The comparator, or null if priority queue uses elements'
70 * natural ordering.
71 */
72 private final Comparator<? super E> comparator;
73
74 /**
75 * The number of times this priority queue has been
76 * <i>structurally modified</i>. See AbstractList for gory details.
77 */
78 private transient int modCount = 0;
79
80 /**
81 * Creates a <tt>PriorityQueue</tt> with the default initial capacity
82 * (11) that orders its elements according to their natural
83 * ordering (using <tt>Comparable</tt>.)
84 */
85 public PriorityQueue() {
86 this(DEFAULT_INITIAL_CAPACITY, null);
87 }
88
89 /**
90 * Creates a <tt>PriorityQueue</tt> with the specified initial capacity
91 * that orders its elements according to their natural ordering
92 * (using <tt>Comparable</tt>.)
93 *
94 * @param initialCapacity the initial capacity for this priority queue.
95 */
96 public PriorityQueue(int initialCapacity) {
97 this(initialCapacity, null);
98 }
99
100 /**
101 * Creates a <tt>PriorityQueue</tt> with the specified initial capacity
102 * that orders its elements according to the specified comparator.
103 *
104 * @param initialCapacity the initial capacity for this priority queue.
105 * @param comparator the comparator used to order this priority queue.
106 * If <tt>null</tt> then the order depends on the elements' natural
107 * ordering.
108 * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
109 * than 1
110 */
111 public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
112 if (initialCapacity < 1)
113 throw new IllegalArgumentException();
114 this.queue = new Object[initialCapacity + 1];
115 this.comparator = comparator;
116 }
117
118 /**
119 * Common code to initialize underlying queue array across
120 * constructors below.
121 */
122 private void initializeArray(Collection<? extends E> c) {
123 int sz = c.size();
124 int initialCapacity = (int)Math.min((sz * 110L) / 100,
125 Integer.MAX_VALUE - 1);
126 if (initialCapacity < 1)
127 initialCapacity = 1;
128
129 this.queue = new Object[initialCapacity + 1];
130 }
131
132 /**
133 * Initially fill elements of the queue array under the
134 * knowledge that it is sorted or is another PQ, in which
135 * case we can just place the elements without fixups.
136 */
137 private void fillFromSorted(Collection<? extends E> c) {
138 for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )
139 queue[++size] = i.next();
140 }
141
142
143 /**
144 * Initially fill elements of the queue array that is
145 * not to our knowledge sorted, so we must add them
146 * one by one.
147 */
148 private void fillFromUnsorted(Collection<? extends E> c) {
149 for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )
150 add(i.next());
151 }
152
153 /**
154 * Creates a <tt>PriorityQueue</tt> containing the elements in the
155 * specified collection. The priority queue has an initial
156 * capacity of 110% of the size of the specified collection or 1
157 * if the collection is empty. If the specified collection is an
158 * instance of a {@link SortedSet} or is another
159 * <tt>PriorityQueue</tt>, the priority queue will be sorted
160 * according to the same comparator, or according to its elements'
161 * natural order if the collection is sorted according to its
162 * elements' natural order. Otherwise, the priority queue is
163 * ordered according to its elements' natural order.
164 *
165 * @param c the collection whose elements are to be placed
166 * into this priority queue.
167 * @throws ClassCastException if elements of the specified collection
168 * cannot be compared to one another according to the priority
169 * queue's ordering.
170 * @throws NullPointerException if <tt>c</tt> or any element within it
171 * is <tt>null</tt>
172 */
173 public PriorityQueue(Collection<? extends E> c) {
174 initializeArray(c);
175 if (c instanceof SortedSet<? extends E>) {
176 SortedSet<? extends E> s = (SortedSet<? extends E>) c;
177 comparator = (Comparator<? super E>)s.comparator();
178 fillFromSorted(s);
179 }
180 else if (c instanceof PriorityQueue<? extends E>) {
181 PriorityQueue<? extends E> s = (PriorityQueue<? extends E>) c;
182 comparator = (Comparator<? super E>)s.comparator();
183 fillFromSorted(s);
184 }
185 else {
186 comparator = null;
187 fillFromUnsorted(c);
188 }
189 }
190
191 /**
192 * Creates a <tt>PriorityQueue</tt> containing the elements in the
193 * specified collection. The priority queue has an initial
194 * capacity of 110% of the size of the specified collection or 1
195 * if the collection is empty. This priority queue will be sorted
196 * according to the same comparator as the given collection, or
197 * according to its elements' natural order if the collection is
198 * sorted according to its elements' natural order.
199 *
200 * @param c the collection whose elements are to be placed
201 * into this priority queue.
202 * @throws ClassCastException if elements of the specified collection
203 * cannot be compared to one another according to the priority
204 * queue's ordering.
205 * @throws NullPointerException if <tt>c</tt> or any element within it
206 * is <tt>null</tt>
207 */
208 public PriorityQueue(PriorityQueue<? extends E> c) {
209 initializeArray(c);
210 comparator = (Comparator<? super E>)c.comparator();
211 fillFromSorted(c);
212 }
213
214 /**
215 * Creates a <tt>PriorityQueue</tt> containing the elements in the
216 * specified collection. The priority queue has an initial
217 * capacity of 110% of the size of the specified collection or 1
218 * if the collection is empty. This priority queue will be sorted
219 * according to the same comparator as the given collection, or
220 * according to its elements' natural order if the collection is
221 * sorted according to its elements' natural order.
222 *
223 * @param c the collection whose elements are to be placed
224 * into this priority queue.
225 * @throws ClassCastException if elements of the specified collection
226 * cannot be compared to one another according to the priority
227 * queue's ordering.
228 * @throws NullPointerException if <tt>c</tt> or any element within it
229 * is <tt>null</tt>
230 */
231 public PriorityQueue(SortedSet<? extends E> c) {
232 initializeArray(c);
233 comparator = (Comparator<? super E>)c.comparator();
234 fillFromSorted(c);
235 }
236
237 /**
238 * Resize array, if necessary, to be able to hold given index
239 */
240 private void grow(int index) {
241 int newlen = queue.length;
242 if (index < newlen) // don't need to grow
243 return;
244 if (index == Integer.MAX_VALUE)
245 throw new OutOfMemoryError();
246 while (newlen <= index) {
247 if (newlen >= Integer.MAX_VALUE / 2) // avoid overflow
248 newlen = Integer.MAX_VALUE;
249 else
250 newlen <<= 2;
251 }
252 Object[] newQueue = new Object[newlen];
253 System.arraycopy(queue, 0, newQueue, 0, queue.length);
254 queue = newQueue;
255 }
256
257 // Queue Methods
258
259 /**
260 * Add the specified element to this priority queue.
261 *
262 * @return <tt>true</tt>
263 * @throws ClassCastException if the specified element cannot be compared
264 * with elements currently in the priority queue according
265 * to the priority queue's ordering.
266 * @throws NullPointerException if the specified element is <tt>null</tt>.
267 */
268 public boolean offer(E o) {
269 if (o == null)
270 throw new NullPointerException();
271 modCount++;
272 ++size;
273
274 // Grow backing store if necessary
275 if (size >= queue.length)
276 grow(size);
277
278 queue[size] = o;
279 fixUp(size);
280 return true;
281 }
282
283 public E poll() {
284 if (size == 0)
285 return null;
286 return (E) remove(1);
287 }
288
289 public E peek() {
290 return (E) queue[1];
291 }
292
293 // Collection Methods
294
295 // these first two override just to get the throws docs
296
297 /**
298 * @throws NullPointerException if the specified element is <tt>null</tt>.
299 * @throws ClassCastException if the specified element cannot be compared
300 * with elements currently in the priority queue according
301 * to the priority queue's ordering.
302 */
303 public boolean add(E o) {
304 return super.add(o);
305 }
306
307 /**
308 * @throws ClassCastException if any element cannot be compared
309 * with elements currently in the priority queue according
310 * to the priority queue's ordering.
311 * @throws NullPointerException if <tt>c</tt> or any element in <tt>c</tt>
312 * is <tt>null</tt>
313 */
314 public boolean addAll(Collection<? extends E> c) {
315 return super.addAll(c);
316 }
317
318 public boolean remove(Object o) {
319 if (o == null)
320 return false;
321
322 if (comparator == null) {
323 for (int i = 1; i <= size; i++) {
324 if (((Comparable<E>)queue[i]).compareTo((E)o) == 0) {
325 remove(i);
326 return true;
327 }
328 }
329 } else {
330 for (int i = 1; i <= size; i++) {
331 if (comparator.compare((E)queue[i], (E)o) == 0) {
332 remove(i);
333 return true;
334 }
335 }
336 }
337 return false;
338 }
339
340 public Iterator<E> iterator() {
341 return new Itr();
342 }
343
344 private class Itr implements Iterator<E> {
345 /**
346 * Index (into queue array) of element to be returned by
347 * subsequent call to next.
348 */
349 private int cursor = 1;
350
351 /**
352 * Index of element returned by most recent call to next or
353 * previous. Reset to 0 if this element is deleted by a call
354 * to remove.
355 */
356 private int lastRet = 0;
357
358 /**
359 * The modCount value that the iterator believes that the backing
360 * List should have. If this expectation is violated, the iterator
361 * has detected concurrent modification.
362 */
363 private int expectedModCount = modCount;
364
365 public boolean hasNext() {
366 return cursor <= size;
367 }
368
369 public E next() {
370 checkForComodification();
371 if (cursor > size)
372 throw new NoSuchElementException();
373 E result = (E) queue[cursor];
374 lastRet = cursor++;
375 return result;
376 }
377
378 public void remove() {
379 if (lastRet == 0)
380 throw new IllegalStateException();
381 checkForComodification();
382
383 PriorityQueue.this.remove(lastRet);
384 if (lastRet < cursor)
385 cursor--;
386 lastRet = 0;
387 expectedModCount = modCount;
388 }
389
390 final void checkForComodification() {
391 if (modCount != expectedModCount)
392 throw new ConcurrentModificationException();
393 }
394 }
395
396 /**
397 * Returns the number of elements in this priority queue.
398 *
399 * @return the number of elements in this priority queue.
400 */
401 public int size() {
402 return size;
403 }
404
405 /**
406 * Remove all elements from the priority queue.
407 */
408 public void clear() {
409 modCount++;
410
411 // Null out element references to prevent memory leak
412 for (int i=1; i<=size; i++)
413 queue[i] = null;
414
415 size = 0;
416 }
417
418 /**
419 * Removes and returns the ith element from queue. Recall
420 * that queue is one-based, so 1 <= i <= size.
421 *
422 * XXX: Could further special-case i==size, but is it worth it?
423 * XXX: Could special-case i==0, but is it worth it?
424 */
425 private E remove(int i) {
426 assert i <= size;
427 modCount++;
428
429 E result = (E) queue[i];
430 queue[i] = queue[size];
431 queue[size--] = null; // Drop extra ref to prevent memory leak
432 if (i <= size)
433 fixDown(i);
434 return result;
435 }
436
437 /**
438 * Establishes the heap invariant (described above) assuming the heap
439 * satisfies the invariant except possibly for the leaf-node indexed by k
440 * (which may have a nextExecutionTime less than its parent's).
441 *
442 * This method functions by "promoting" queue[k] up the hierarchy
443 * (by swapping it with its parent) repeatedly until queue[k]
444 * is greater than or equal to its parent.
445 */
446 private void fixUp(int k) {
447 if (comparator == null) {
448 while (k > 1) {
449 int j = k >> 1;
450 if (((Comparable<E>)queue[j]).compareTo((E)queue[k]) <= 0)
451 break;
452 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
453 k = j;
454 }
455 } else {
456 while (k > 1) {
457 int j = k >> 1;
458 if (comparator.compare((E)queue[j], (E)queue[k]) <= 0)
459 break;
460 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
461 k = j;
462 }
463 }
464 }
465
466 /**
467 * Establishes the heap invariant (described above) in the subtree
468 * rooted at k, which is assumed to satisfy the heap invariant except
469 * possibly for node k itself (which may be greater than its children).
470 *
471 * This method functions by "demoting" queue[k] down the hierarchy
472 * (by swapping it with its smaller child) repeatedly until queue[k]
473 * is less than or equal to its children.
474 */
475 private void fixDown(int k) {
476 int j;
477 if (comparator == null) {
478 while ((j = k << 1) <= size) {
479 if (j<size && ((Comparable<E>)queue[j]).compareTo((E)queue[j+1]) > 0)
480 j++; // j indexes smallest kid
481 if (((Comparable<E>)queue[k]).compareTo((E)queue[j]) <= 0)
482 break;
483 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
484 k = j;
485 }
486 } else {
487 while ((j = k << 1) <= size) {
488 if (j < size && comparator.compare((E)queue[j], (E)queue[j+1]) > 0)
489 j++; // j indexes smallest kid
490 if (comparator.compare((E)queue[k], (E)queue[j]) <= 0)
491 break;
492 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
493 k = j;
494 }
495 }
496 }
497
498 public Comparator<? super E> comparator() {
499 return comparator;
500 }
501
502 /**
503 * Save the state of the instance to a stream (that
504 * is, serialize it).
505 *
506 * @serialData The length of the array backing the instance is
507 * emitted (int), followed by all of its elements (each an
508 * <tt>Object</tt>) in the proper order.
509 * @param s the stream
510 */
511 private void writeObject(java.io.ObjectOutputStream s)
512 throws java.io.IOException{
513 // Write out element count, and any hidden stuff
514 s.defaultWriteObject();
515
516 // Write out array length
517 s.writeInt(queue.length);
518
519 // Write out all elements in the proper order.
520 for (int i=0; i<size; i++)
521 s.writeObject(queue[i]);
522 }
523
524 /**
525 * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
526 * deserialize it).
527 * @param s the stream
528 */
529 private void readObject(java.io.ObjectInputStream s)
530 throws java.io.IOException, ClassNotFoundException {
531 // Read in size, and any hidden stuff
532 s.defaultReadObject();
533
534 // Read in array length and allocate array
535 int arrayLength = s.readInt();
536 queue = new Object[arrayLength];
537
538 // Read in all elements in the proper order.
539 for (int i=0; i<size; i++)
540 queue[i] = s.readObject();
541 }
542
543 }
544