ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/PriorityQueue.java
Revision: 1.38
Committed: Mon Sep 1 12:23:28 2003 UTC (20 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.37: +9 -1 lines
Log Message:
Adjust headers; continue 1.5.0 resynch

File Contents

# Content
1 /*
2 * %W% %E%
3 *
4 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
5 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6 */
7
8 package java.util;
9
10 /**
11 * An unbounded priority {@linkplain Queue queue} based on a priority heap.
12 * This queue orders elements according to an order specified at construction
13 * time, which is specified in the same manner as {@link java.util.TreeSet}
14 * and {@link java.util.TreeMap}: elements are ordered either according to
15 * their <i>natural order</i> (see {@link Comparable}), or according to a
16 * {@link java.util.Comparator}, depending on which constructor is used.
17 * <p>The <em>head</em> of this queue is the <em>least</em> element with
18 * respect to the specified ordering. If multiple elements are tied for least
19 * value, the head is one of those elements. A priority queue does not permit
20 * <tt>null</tt> elements.
21 *
22 * <p>The {@link #remove()} and {@link #poll()} methods remove and
23 * return the head of the queue.
24 *
25 * <p>The {@link #element()} and {@link #peek()} methods return, but do
26 * not delete, the head of the queue.
27 *
28 * <p>A priority queue has a <i>capacity</i>. The capacity is the
29 * size of the array used internally to store the elements on the
30 * queue.
31 * It is always at least as large as the queue size. As
32 * elements are added to a priority queue, its capacity grows
33 * automatically. The details of the growth policy are not specified.
34 *
35 * <p>The Iterator provided in method {@link #iterator()} is <em>not</em>
36 * guaranteed to traverse the elements of the PriorityQueue in any
37 * particular order. If you need ordered traversal, consider using
38 * <tt>Arrays.sort(pq.toArray())</tt>.
39 *
40 * <p> <strong>Note that this implementation is not synchronized.</strong>
41 * Multiple threads should not access a <tt>PriorityQueue</tt>
42 * instance concurrently if any of the threads modifies the list
43 * structurally. Instead, use the thread-safe {@link
44 * java.util.concurrent.PriorityBlockingQueue} class.
45 *
46 *
47 * <p>Implementation note: this implementation provides O(log(n)) time
48 * for the insertion methods (<tt>offer</tt>, <tt>poll</tt>,
49 * <tt>remove()</tt> and <tt>add</tt>) methods; linear time for the
50 * <tt>remove(Object)</tt> and <tt>contains(Object)</tt> methods; and
51 * constant time for the retrieval methods (<tt>peek</tt>,
52 * <tt>element</tt>, and <tt>size</tt>).
53 *
54 * <p>This class is a member of the
55 * <a href="{@docRoot}/../guide/collections/index.html">
56 * Java Collections Framework</a>.
57 * @since 1.5
58 * @version %I%, %G%
59 * @author Josh Bloch
60 */
61 public class PriorityQueue<E> extends AbstractQueue<E>
62 implements Queue<E>, java.io.Serializable {
63
64 private static final long serialVersionUID = -7720805057305804111L;
65
66 private static final int DEFAULT_INITIAL_CAPACITY = 11;
67
68 /**
69 * Priority queue represented as a balanced binary heap: the two children
70 * of queue[n] are queue[2*n] and queue[2*n + 1]. The priority queue is
71 * ordered by comparator, or by the elements' natural ordering, if
72 * comparator is null: For each node n in the heap and each descendant d
73 * of n, n <= d.
74 *
75 * The element with the lowest value is in queue[1], assuming the queue is
76 * nonempty. (A one-based array is used in preference to the traditional
77 * zero-based array to simplify parent and child calculations.)
78 *
79 * queue.length must be >= 2, even if size == 0.
80 */
81 private transient Object[] queue;
82
83 /**
84 * The number of elements in the priority queue.
85 */
86 private int size = 0;
87
88 /**
89 * The comparator, or null if priority queue uses elements'
90 * natural ordering.
91 */
92 private final Comparator<? super E> comparator;
93
94 /**
95 * The number of times this priority queue has been
96 * <i>structurally modified</i>. See AbstractList for gory details.
97 */
98 private transient int modCount = 0;
99
100 /**
101 * Creates a <tt>PriorityQueue</tt> with the default initial capacity
102 * (11) that orders its elements according to their natural
103 * ordering (using <tt>Comparable</tt>).
104 */
105 public PriorityQueue() {
106 this(DEFAULT_INITIAL_CAPACITY, null);
107 }
108
109 /**
110 * Creates a <tt>PriorityQueue</tt> with the specified initial capacity
111 * that orders its elements according to their natural ordering
112 * (using <tt>Comparable</tt>).
113 *
114 * @param initialCapacity the initial capacity for this priority queue.
115 * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
116 * than 1
117 */
118 public PriorityQueue(int initialCapacity) {
119 this(initialCapacity, null);
120 }
121
122 /**
123 * Creates a <tt>PriorityQueue</tt> with the specified initial capacity
124 * that orders its elements according to the specified comparator.
125 *
126 * @param initialCapacity the initial capacity for this priority queue.
127 * @param comparator the comparator used to order this priority queue.
128 * If <tt>null</tt> then the order depends on the elements' natural
129 * ordering.
130 * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
131 * than 1
132 */
133 public PriorityQueue(int initialCapacity,
134 Comparator<? super E> comparator) {
135 if (initialCapacity < 1)
136 throw new IllegalArgumentException();
137 this.queue = new Object[initialCapacity + 1];
138 this.comparator = comparator;
139 }
140
141 /**
142 * Common code to initialize underlying queue array across
143 * constructors below.
144 */
145 private void initializeArray(Collection<? extends E> c) {
146 int sz = c.size();
147 int initialCapacity = (int)Math.min((sz * 110L) / 100,
148 Integer.MAX_VALUE - 1);
149 if (initialCapacity < 1)
150 initialCapacity = 1;
151
152 this.queue = new Object[initialCapacity + 1];
153 }
154
155 /**
156 * Initially fill elements of the queue array under the
157 * knowledge that it is sorted or is another PQ, in which
158 * case we can just place the elements in the order presented.
159 */
160 private void fillFromSorted(Collection<? extends E> c) {
161 for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )
162 queue[++size] = i.next();
163 }
164
165 /**
166 * Initially fill elements of the queue array that is not to our knowledge
167 * sorted, so we must rearrange the elements to guarantee the heap
168 * invariant.
169 */
170 private void fillFromUnsorted(Collection<? extends E> c) {
171 for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )
172 queue[++size] = i.next();
173 heapify();
174 }
175
176 /**
177 * Creates a <tt>PriorityQueue</tt> containing the elements in the
178 * specified collection. The priority queue has an initial
179 * capacity of 110% of the size of the specified collection or 1
180 * if the collection is empty. If the specified collection is an
181 * instance of a {@link java.util.SortedSet} or is another
182 * <tt>PriorityQueue</tt>, the priority queue will be sorted
183 * according to the same comparator, or according to its elements'
184 * natural order if the collection is sorted according to its
185 * elements' natural order. Otherwise, the priority queue is
186 * ordered according to its elements' natural order.
187 *
188 * @param c the collection whose elements are to be placed
189 * into this priority queue.
190 * @throws ClassCastException if elements of the specified collection
191 * cannot be compared to one another according to the priority
192 * queue's ordering.
193 * @throws NullPointerException if <tt>c</tt> or any element within it
194 * is <tt>null</tt>
195 */
196 public PriorityQueue(Collection<? extends E> c) {
197 initializeArray(c);
198 if (c instanceof SortedSet) {
199 // @fixme double-cast workaround for compiler
200 SortedSet<? extends E> s = (SortedSet<? extends E>) (SortedSet)c;
201 comparator = (Comparator<? super E>)s.comparator();
202 fillFromSorted(s);
203 } else if (c instanceof PriorityQueue) {
204 PriorityQueue<? extends E> s = (PriorityQueue<? extends E>) c;
205 comparator = (Comparator<? super E>)s.comparator();
206 fillFromSorted(s);
207 } else {
208 comparator = null;
209 fillFromUnsorted(c);
210 }
211 }
212
213 /**
214 * Creates a <tt>PriorityQueue</tt> containing the elements in the
215 * specified collection. The priority queue has an initial
216 * capacity of 110% of the size of the specified collection or 1
217 * if the collection is empty. This priority queue will be sorted
218 * according to the same comparator as the given collection, or
219 * according to its elements' natural order if the collection is
220 * sorted according to its elements' natural order.
221 *
222 * @param c the collection whose elements are to be placed
223 * into this priority queue.
224 * @throws ClassCastException if elements of the specified collection
225 * cannot be compared to one another according to the priority
226 * queue's ordering.
227 * @throws NullPointerException if <tt>c</tt> or any element within it
228 * is <tt>null</tt>
229 */
230 public PriorityQueue(PriorityQueue<? extends E> c) {
231 initializeArray(c);
232 comparator = (Comparator<? super E>)c.comparator();
233 fillFromSorted(c);
234 }
235
236 /**
237 * Creates a <tt>PriorityQueue</tt> containing the elements in the
238 * specified collection. The priority queue has an initial
239 * capacity of 110% of the size of the specified collection or 1
240 * if the collection is empty. This priority queue will be sorted
241 * according to the same comparator as the given collection, or
242 * according to its elements' natural order if the collection is
243 * sorted according to its elements' natural order.
244 *
245 * @param c the collection whose elements are to be placed
246 * into this priority queue.
247 * @throws ClassCastException if elements of the specified collection
248 * cannot be compared to one another according to the priority
249 * queue's ordering.
250 * @throws NullPointerException if <tt>c</tt> or any element within it
251 * is <tt>null</tt>
252 */
253 public PriorityQueue(SortedSet<? extends E> c) {
254 initializeArray(c);
255 comparator = (Comparator<? super E>)c.comparator();
256 fillFromSorted(c);
257 }
258
259 /**
260 * Resize array, if necessary, to be able to hold given index
261 */
262 private void grow(int index) {
263 int newlen = queue.length;
264 if (index < newlen) // don't need to grow
265 return;
266 if (index == Integer.MAX_VALUE)
267 throw new OutOfMemoryError();
268 while (newlen <= index) {
269 if (newlen >= Integer.MAX_VALUE / 2) // avoid overflow
270 newlen = Integer.MAX_VALUE;
271 else
272 newlen <<= 2;
273 }
274 Object[] newQueue = new Object[newlen];
275 System.arraycopy(queue, 0, newQueue, 0, queue.length);
276 queue = newQueue;
277 }
278
279
280 // Queue Methods
281
282 /**
283 * Add the specified element to this priority queue.
284 *
285 * @return <tt>true</tt>
286 * @throws ClassCastException if the specified element cannot be compared
287 * with elements currently in the priority queue according
288 * to the priority queue's ordering.
289 * @throws NullPointerException if the specified element is <tt>null</tt>.
290 */
291 public boolean offer(E o) {
292 if (o == null)
293 throw new NullPointerException();
294 modCount++;
295 ++size;
296
297 // Grow backing store if necessary
298 if (size >= queue.length)
299 grow(size);
300
301 queue[size] = o;
302 fixUp(size);
303 return true;
304 }
305
306 public E poll() {
307 if (size == 0)
308 return null;
309 return remove();
310 }
311
312 public E peek() {
313 return (E) queue[1];
314 }
315
316 // Collection Methods - the first two override to update docs
317
318 /**
319 * Adds the specified element to this queue.
320 * @return <tt>true</tt> (as per the general contract of
321 * <tt>Collection.add</tt>).
322 *
323 * @throws NullPointerException {@inheritDoc}
324 * @throws ClassCastException if the specified element cannot be compared
325 * with elements currently in the priority queue according
326 * to the priority queue's ordering.
327 */
328 public boolean add(E o) {
329 return super.add(o);
330 }
331
332
333 /**
334 * Adds all of the elements in the specified collection to this queue.
335 * The behavior of this operation is undefined if
336 * the specified collection is modified while the operation is in
337 * progress. (This implies that the behavior of this call is undefined if
338 * the specified collection is this queue, and this queue is nonempty.)
339 * <p>
340 * This implementation iterates over the specified collection, and adds
341 * each object returned by the iterator to this collection, in turn.
342 * @throws NullPointerException {@inheritDoc}
343 * @throws ClassCastException if any element cannot be compared
344 * with elements currently in the priority queue according
345 * to the priority queue's ordering.
346 */
347 public boolean addAll(Collection<? extends E> c) {
348 return super.addAll(c);
349 }
350
351
352 /**
353 * Removes a single instance of the specified element from this
354 * queue, if it is present. More formally,
355 * removes an element <tt>e</tt> such that <tt>(o==null ? e==null :
356 * o.equals(e))</tt>, if the queue contains one or more such
357 * elements. Returns <tt>true</tt> if the queue contained the
358 * specified element (or equivalently, if the queue changed as a
359 * result of the call).
360 *
361 * <p>This implementation iterates over the queue looking for the
362 * specified element. If it finds the element, it removes the element
363 * from the queue using the iterator's remove method.<p>
364 *
365 */
366 public boolean remove(Object o) {
367 if (o == null)
368 return false;
369
370 if (comparator == null) {
371 for (int i = 1; i <= size; i++) {
372 if (((Comparable<E>)queue[i]).compareTo((E)o) == 0) {
373 removeAt(i);
374 return true;
375 }
376 }
377 } else {
378 for (int i = 1; i <= size; i++) {
379 if (comparator.compare((E)queue[i], (E)o) == 0) {
380 removeAt(i);
381 return true;
382 }
383 }
384 }
385 return false;
386 }
387
388 /**
389 * Returns an iterator over the elements in this queue. The iterator
390 * does not return the elements in any particular order.
391 *
392 * @return an iterator over the elements in this queue.
393 */
394 public Iterator<E> iterator() {
395 return new Itr();
396 }
397
398 private class Itr implements Iterator<E> {
399
400 /**
401 * Index (into queue array) of element to be returned by
402 * subsequent call to next.
403 */
404 private int cursor = 1;
405
406 /**
407 * Index of element returned by most recent call to next,
408 * unless that element came from the forgetMeNot list.
409 * Reset to 0 if element is deleted by a call to remove.
410 */
411 private int lastRet = 0;
412
413 /**
414 * The modCount value that the iterator believes that the backing
415 * List should have. If this expectation is violated, the iterator
416 * has detected concurrent modification.
417 */
418 private int expectedModCount = modCount;
419
420 /**
421 * A list of elements that were moved from the unvisited portion of
422 * the heap into the visited portion as a result of "unlucky" element
423 * removals during the iteration. (Unlucky element removals are those
424 * that require a fixup instead of a fixdown.) We must visit all of
425 * the elements in this list to complete the iteration. We do this
426 * after we've completed the "normal" iteration.
427 *
428 * We expect that most iterations, even those involving removals,
429 * will not use need to store elements in this field.
430 */
431 private ArrayList<E> forgetMeNot = null;
432
433 /**
434 * Element returned by the most recent call to next iff that
435 * element was drawn from the forgetMeNot list.
436 */
437 private Object lastRetElt = null;
438
439 public boolean hasNext() {
440 return cursor <= size || forgetMeNot != null;
441 }
442
443 public E next() {
444 checkForComodification();
445 E result;
446 if (cursor <= size) {
447 result = (E) queue[cursor];
448 lastRet = cursor++;
449 }
450 else if (forgetMeNot == null)
451 throw new NoSuchElementException();
452 else {
453 int remaining = forgetMeNot.size();
454 result = forgetMeNot.remove(remaining - 1);
455 if (remaining == 1)
456 forgetMeNot = null;
457 lastRet = 0;
458 lastRetElt = result;
459 }
460 return result;
461 }
462
463 public void remove() {
464 checkForComodification();
465
466 if (lastRet != 0) {
467 E moved = PriorityQueue.this.removeAt(lastRet);
468 lastRet = 0;
469 if (moved == null) {
470 cursor--;
471 } else {
472 if (forgetMeNot == null)
473 forgetMeNot = new ArrayList<E>();
474 forgetMeNot.add(moved);
475 }
476 } else if (lastRetElt != null) {
477 PriorityQueue.this.remove(lastRetElt);
478 lastRetElt = null;
479 } else {
480 throw new IllegalStateException();
481 }
482
483 expectedModCount = modCount;
484 }
485
486 final void checkForComodification() {
487 if (modCount != expectedModCount)
488 throw new ConcurrentModificationException();
489 }
490 }
491
492 public int size() {
493 return size;
494 }
495
496 /**
497 * Remove all elements from the priority queue.
498 */
499 public void clear() {
500 modCount++;
501
502 // Null out element references to prevent memory leak
503 for (int i=1; i<=size; i++)
504 queue[i] = null;
505
506 size = 0;
507 }
508
509 /**
510 * Removes and returns the first element from queue.
511 */
512 public E remove() {
513 if (size == 0)
514 throw new NoSuchElementException();
515 modCount++;
516
517 E result = (E) queue[1];
518 queue[1] = queue[size];
519 queue[size--] = null; // Drop extra ref to prevent memory leak
520 if (size > 1)
521 fixDown(1);
522
523 return result;
524 }
525
526 /**
527 * Removes and returns the ith element from queue. (Recall that queue
528 * is one-based, so 1 <= i <= size.)
529 *
530 * Normally this method leaves the elements at positions from 1 up to i-1,
531 * inclusive, untouched. Under these circumstances, it returns null.
532 * Occasionally, in order to maintain the heap invariant, it must move
533 * the last element of the list to some index in the range [2, i-1],
534 * and move the element previously at position (i/2) to position i.
535 * Under these circumstances, this method returns the element that was
536 * previously at the end of the list and is now at some position between
537 * 2 and i-1 inclusive.
538 */
539 private E removeAt(int i) {
540 assert i > 0 && i <= size;
541 modCount++;
542
543 E moved = (E) queue[size];
544 queue[i] = moved;
545 queue[size--] = null; // Drop extra ref to prevent memory leak
546 if (i <= size) {
547 fixDown(i);
548 if (queue[i] == moved) {
549 fixUp(i);
550 if (queue[i] != moved)
551 return moved;
552 }
553 }
554 return null;
555 }
556
557 /**
558 * Establishes the heap invariant (described above) assuming the heap
559 * satisfies the invariant except possibly for the leaf-node indexed by k
560 * (which may have a nextExecutionTime less than its parent's).
561 *
562 * This method functions by "promoting" queue[k] up the hierarchy
563 * (by swapping it with its parent) repeatedly until queue[k]
564 * is greater than or equal to its parent.
565 */
566 private void fixUp(int k) {
567 if (comparator == null) {
568 while (k > 1) {
569 int j = k >> 1;
570 if (((Comparable<E>)queue[j]).compareTo((E)queue[k]) <= 0)
571 break;
572 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
573 k = j;
574 }
575 } else {
576 while (k > 1) {
577 int j = k >>> 1;
578 if (comparator.compare((E)queue[j], (E)queue[k]) <= 0)
579 break;
580 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
581 k = j;
582 }
583 }
584 }
585
586 /**
587 * Establishes the heap invariant (described above) in the subtree
588 * rooted at k, which is assumed to satisfy the heap invariant except
589 * possibly for node k itself (which may be greater than its children).
590 *
591 * This method functions by "demoting" queue[k] down the hierarchy
592 * (by swapping it with its smaller child) repeatedly until queue[k]
593 * is less than or equal to its children.
594 */
595 private void fixDown(int k) {
596 int j;
597 if (comparator == null) {
598 while ((j = k << 1) <= size && (j > 0)) {
599 if (j<size &&
600 ((Comparable<E>)queue[j]).compareTo((E)queue[j+1]) > 0)
601 j++; // j indexes smallest kid
602
603 if (((Comparable<E>)queue[k]).compareTo((E)queue[j]) <= 0)
604 break;
605 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
606 k = j;
607 }
608 } else {
609 while ((j = k << 1) <= size && (j > 0)) {
610 if (j<size &&
611 comparator.compare((E)queue[j], (E)queue[j+1]) > 0)
612 j++; // j indexes smallest kid
613 if (comparator.compare((E)queue[k], (E)queue[j]) <= 0)
614 break;
615 Object tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
616 k = j;
617 }
618 }
619 }
620
621 /**
622 * Establishes the heap invariant (described above) in the entire tree,
623 * assuming nothing about the order of the elements prior to the call.
624 */
625 private void heapify() {
626 for (int i = size/2; i >= 1; i--)
627 fixDown(i);
628 }
629
630 /**
631 * Returns the comparator used to order this collection, or <tt>null</tt>
632 * if this collection is sorted according to its elements natural ordering
633 * (using <tt>Comparable</tt>).
634 *
635 * @return the comparator used to order this collection, or <tt>null</tt>
636 * if this collection is sorted according to its elements natural ordering.
637 */
638 public Comparator<? super E> comparator() {
639 return comparator;
640 }
641
642 /**
643 * Save the state of the instance to a stream (that
644 * is, serialize it).
645 *
646 * @serialData The length of the array backing the instance is
647 * emitted (int), followed by all of its elements (each an
648 * <tt>Object</tt>) in the proper order.
649 * @param s the stream
650 */
651 private void writeObject(java.io.ObjectOutputStream s)
652 throws java.io.IOException{
653 // Write out element count, and any hidden stuff
654 s.defaultWriteObject();
655
656 // Write out array length
657 s.writeInt(queue.length);
658
659 // Write out all elements in the proper order.
660 for (int i=0; i<size; i++)
661 s.writeObject(queue[i]);
662 }
663
664 /**
665 * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
666 * deserialize it).
667 * @param s the stream
668 */
669 private void readObject(java.io.ObjectInputStream s)
670 throws java.io.IOException, ClassNotFoundException {
671 // Read in size, and any hidden stuff
672 s.defaultReadObject();
673
674 // Read in array length and allocate array
675 int arrayLength = s.readInt();
676 queue = new Object[arrayLength];
677
678 // Read in all elements in the proper order.
679 for (int i=0; i<size; i++)
680 queue[i] = (E) s.readObject();
681 }
682
683 }