ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/PriorityQueue.java
(Generate patch)

Comparing jsr166/src/main/java/util/PriorityQueue.java (file contents):
Revision 1.52 by dl, Tue Nov 22 11:44:47 2005 UTC vs.
Revision 1.62 by jsr166, Thu Feb 16 08:17:21 2006 UTC

# Line 1 | Line 1
1   /*
2 < * @(#)PriorityQueue.java       1.8 05/08/27
2 > * %W% %E%
3   *
4 < * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
4 > * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5   * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6   */
7  
8   package java.util;
9 import java.util.*; // for javadoc (till 6280605 is fixed)
9  
10   /**
11   * An unbounded priority {@linkplain Queue queue} based on a priority
# Line 56 | Line 55 | import java.util.*; // for javadoc (till
55   * <a href="{@docRoot}/../guide/collections/index.html">
56   * Java Collections Framework</a>.
57   * @since 1.5
58 < * @version 1.8, 08/27/05
58 > * @version %I%, %G%
59   * @author Josh Bloch
60   * @param <E> the type of elements held in this collection
61   */
# Line 68 | Line 67 | public class PriorityQueue<E> extends Ab
67      private static final int DEFAULT_INITIAL_CAPACITY = 11;
68  
69      /**
70 <     * Priority queue represented as a balanced binary heap: the two children
71 <     * of queue[n] are queue[2*n] and queue[2*n + 1].  The priority queue is
72 <     * ordered by comparator, or by the elements' natural ordering, if
73 <     * comparator is null:  For each node n in the heap and each descendant d
74 <     * of n, n <= d.
75 <     *
77 <     * The element with the lowest value is in queue[1], assuming the queue is
78 <     * nonempty.  (A one-based array is used in preference to the traditional
79 <     * zero-based array to simplify parent and child calculations.)
80 <     *
81 <     * queue.length must be >= 2, even if size == 0.
70 >     * Priority queue represented as a balanced binary heap: the two
71 >     * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
72 >     * priority queue is ordered by comparator, or by the elements'
73 >     * natural ordering, if comparator is null: For each node n in the
74 >     * heap and each descendant d of n, n <= d.  The element with the
75 >     * lowest value is in queue[0], assuming the queue is nonempty.
76       */
77      private transient Object[] queue;
78  
# Line 134 | Line 128 | public class PriorityQueue<E> extends Ab
128       */
129      public PriorityQueue(int initialCapacity,
130                           Comparator<? super E> comparator) {
131 +        // Note: This restriction of at least one is not actually needed,
132 +        // but continues for 1.5 compatibility
133          if (initialCapacity < 1)
134              throw new IllegalArgumentException();
135 <        this.queue = new Object[initialCapacity + 1];
135 >        this.queue = new Object[initialCapacity];
136          this.comparator = comparator;
137      }
138  
139      /**
144     * Common code to initialize underlying queue array across
145     * constructors below.
146     */
147    private void initializeArray(Collection<? extends E> c) {
148        int sz = c.size();
149        int initialCapacity = (int)Math.min((sz * 110L) / 100,
150                                            Integer.MAX_VALUE - 1);
151        if (initialCapacity < 1)
152            initialCapacity = 1;
153
154        this.queue = new Object[initialCapacity + 1];
155    }
156
157    /**
158     * Initially fill elements of the queue array under the
159     * knowledge that it is sorted or is another PQ, in which
160     * case we can just place the elements in the order presented.
161     */
162    private void fillFromSorted(Collection<? extends E> c) {
163        for (Iterator<? extends E> i = c.iterator(); i.hasNext(); ) {
164            int k = ++size;
165            if (k >= queue.length)
166                grow(k);
167            queue[k] = i.next();
168        }
169    }
170
171    /**
172     * Initially fill elements of the queue array that is not to our knowledge
173     * sorted, so we must rearrange the elements to guarantee the heap
174     * invariant.
175     */
176    private void fillFromUnsorted(Collection<? extends E> c) {
177        for (Iterator<? extends E> i = c.iterator(); i.hasNext(); ) {
178            int k = ++size;
179            if (k >= queue.length)
180                grow(k);
181            queue[k] = i.next();
182        }
183        heapify();
184    }
185
186    /**
140       * Creates a <tt>PriorityQueue</tt> containing the elements in the
141 <     * specified collection.  The priority queue has an initial
189 <     * capacity of 110% of the size of the specified collection or 1
190 <     * if the collection is empty.  If the specified collection is an
141 >     * specified collection.   If the specified collection is an
142       * instance of a {@link java.util.SortedSet} or is another
143       * <tt>PriorityQueue</tt>, the priority queue will be ordered
144       * according to the same ordering.  Otherwise, this priority queue
# Line 202 | Line 153 | public class PriorityQueue<E> extends Ab
153       *         of its elements are null
154       */
155      public PriorityQueue(Collection<? extends E> c) {
156 <        initializeArray(c);
157 <        if (c instanceof SortedSet) {
158 <            SortedSet<? extends E> s = (SortedSet<? extends E>)c;
159 <            comparator = (Comparator<? super E>)s.comparator();
160 <            fillFromSorted(s);
161 <        } else if (c instanceof PriorityQueue) {
162 <            PriorityQueue<? extends E> s = (PriorityQueue<? extends E>) c;
163 <            comparator = (Comparator<? super E>)s.comparator();
213 <            fillFromSorted(s);
214 <        } else {
156 >        initFromCollection(c);
157 >        if (c instanceof SortedSet)
158 >            comparator = (Comparator<? super E>)
159 >                ((SortedSet<? extends E>)c).comparator();
160 >        else if (c instanceof PriorityQueue)
161 >            comparator = (Comparator<? super E>)
162 >                ((PriorityQueue<? extends E>)c).comparator();
163 >        else {
164              comparator = null;
165 <            fillFromUnsorted(c);
165 >            heapify();
166          }
167      }
168  
169      /**
170       * Creates a <tt>PriorityQueue</tt> containing the elements in the
171 <     * specified priority queue.  The priority queue has an initial
223 <     * capacity of 110% of the size of the specified priority queue or
224 <     * 1 if the priority queue is empty.  This priority queue will be
171 >     * specified priority queue.  This priority queue will be
172       * ordered according to the same ordering as the given priority
173       * queue.
174       *
# Line 234 | Line 181 | public class PriorityQueue<E> extends Ab
181       *         of its elements are null
182       */
183      public PriorityQueue(PriorityQueue<? extends E> c) {
237        initializeArray(c);
184          comparator = (Comparator<? super E>)c.comparator();
185 <        fillFromSorted(c);
185 >        initFromCollection(c);
186      }
187  
188      /**
189       * Creates a <tt>PriorityQueue</tt> containing the elements in the
190 <     * specified sorted set.  The priority queue has an initial
245 <     * capacity of 110% of the size of the specified sorted set or 1
246 <     * if the sorted set is empty.  This priority queue will be ordered
190 >     * specified sorted set.  This priority queue will be ordered
191       * according to the same ordering as the given sorted set.
192       *
193       * @param  c the sorted set whose elements are to be placed
# Line 255 | Line 199 | public class PriorityQueue<E> extends Ab
199       *         of its elements are null
200       */
201      public PriorityQueue(SortedSet<? extends E> c) {
258        initializeArray(c);
202          comparator = (Comparator<? super E>)c.comparator();
203 <        fillFromSorted(c);
203 >        initFromCollection(c);
204      }
205  
206      /**
207 <     * Resize array, if necessary, to be able to hold given index.
207 >     * Initialize queue array with elements from the given Collection.
208 >     * @param c the collection
209       */
210 <    private void grow(int index) {
211 <        int newlen = queue.length;
212 <        if (index < newlen) // don't need to grow
213 <            return;
214 <        if (index == Integer.MAX_VALUE)
210 >    private void initFromCollection(Collection<? extends E> c) {
211 >        Object[] a = c.toArray();
212 >        // If c.toArray incorrectly doesn't return Object[], copy it.
213 >        if (a.getClass() != Object[].class)
214 >            a = Arrays.copyOf(a, a.length, Object[].class);
215 >        queue = a;
216 >        size = a.length;
217 >    }
218 >
219 >    /**
220 >     * Increases the capacity of the array.
221 >     *
222 >     * @param minCapacity the desired minimum capacity
223 >     */
224 >    private void grow(int minCapacity) {
225 >        if (minCapacity < 0) // overflow
226              throw new OutOfMemoryError();
227 <        while (newlen <= index) {
228 <            if (newlen >= Integer.MAX_VALUE / 2)  // avoid overflow
229 <                newlen = Integer.MAX_VALUE;
230 <            else
231 <                newlen <<= 2;
232 <        }
233 <        queue = Arrays.copyOf(queue, newlen);
227 >        int oldCapacity = queue.length;
228 >        // Double size if small; else grow by 50%
229 >        int newCapacity = ((oldCapacity < 64)?
230 >                           ((oldCapacity + 1) * 2):
231 >                           ((oldCapacity / 2) * 3));
232 >        if (newCapacity < 0) // overflow
233 >            newCapacity = Integer.MAX_VALUE;
234 >        if (newCapacity < minCapacity)
235 >            newCapacity = minCapacity;
236 >        queue = Arrays.copyOf(queue, newCapacity);
237      }
238  
239      /**
# Line 304 | Line 262 | public class PriorityQueue<E> extends Ab
262          if (e == null)
263              throw new NullPointerException();
264          modCount++;
265 <        ++size;
266 <
267 <        // Grow backing store if necessary
268 <        if (size >= queue.length)
269 <            grow(size);
270 <
271 <        queue[size] = e;
272 <        fixUp(size);
265 >        int i = size;
266 >        if (i >= queue.length)
267 >            grow(i + 1);
268 >        size = i + 1;
269 >        if (i == 0)
270 >            queue[0] = e;
271 >        else
272 >            siftUp(i, e);
273          return true;
274      }
275  
276      public E peek() {
277          if (size == 0)
278              return null;
279 <        return (E) queue[1];
279 >        return (E) queue[0];
280      }
281  
282      private int indexOf(Object o) {
283 <        if (o == null)
284 <            return -1;
285 <        for (int i = 1; i <= size; i++)
286 <            if (o.equals(queue[i]))
287 <                return i;
283 >        if (o != null) {
284 >            for (int i = 0; i < size; i++)
285 >                if (o.equals(queue[i]))
286 >                    return i;
287 >        }
288          return -1;
289      }
290  
# Line 351 | Line 309 | public class PriorityQueue<E> extends Ab
309      }
310  
311      /**
312 +     * Version of remove using reference equality, not equals.
313 +     * Needed by iterator.remove.
314 +     *
315 +     * @param o element to be removed from this queue, if present
316 +     * @return <tt>true</tt> if removed
317 +     */
318 +    boolean removeEq(Object o) {
319 +        for (int i = 0; i < size; i++) {
320 +            if (o == queue[i]) {
321 +                removeAt(i);
322 +                return true;
323 +            }
324 +        }
325 +        return false;
326 +    }
327 +
328 +    /**
329       * Returns <tt>true</tt> if this queue contains the specified element.
330       * More formally, returns <tt>true</tt> if and only if this queue contains
331       * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
# Line 370 | Line 345 | public class PriorityQueue<E> extends Ab
345       * maintained by this list.  (In other words, this method must allocate
346       * a new array).  The caller is thus free to modify the returned array.
347       *
348 <     * @return an array containing all of the elements in this queue.
348 >     * @return an array containing all of the elements in this queue
349       */
350      public Object[] toArray() {
351 <        return Arrays.copyOfRange(queue, 1, size+1);
351 >        return Arrays.copyOf(queue, size);
352      }
353  
354      /**
# Line 403 | Line 378 | public class PriorityQueue<E> extends Ab
378      public <T> T[] toArray(T[] a) {
379          if (a.length < size)
380              // Make a new array of a's runtime type, but my contents:
381 <            return (T[]) Arrays.copyOfRange(queue, 1, size+1, a.getClass());
382 <        System.arraycopy(queue, 1, a, 0, size);
381 >            return (T[]) Arrays.copyOf(queue, size, a.getClass());
382 >        System.arraycopy(queue, 0, a, 0, size);
383          if (a.length > size)
384              a[size] = null;
385          return a;
# Line 420 | Line 395 | public class PriorityQueue<E> extends Ab
395          return new Itr();
396      }
397  
398 <    private class Itr implements Iterator<E> {
424 <
398 >    private final class Itr implements Iterator<E> {
399          /**
400           * Index (into queue array) of element to be returned by
401           * subsequent call to next.
402           */
403 <        private int cursor = 1;
403 >        private int cursor = 0;
404  
405          /**
406           * Index of element returned by most recent call to next,
407           * unless that element came from the forgetMeNot list.
408 <         * Reset to 0 if element is deleted by a call to remove.
435 <         */
436 <        private int lastRet = 0;
437 <
438 <        /**
439 <         * The modCount value that the iterator believes that the backing
440 <         * List should have.  If this expectation is violated, the iterator
441 <         * has detected concurrent modification.
408 >         * Set to -1 if element is deleted by a call to remove.
409           */
410 <        private int expectedModCount = modCount;
410 >        private int lastRet = -1;
411  
412          /**
413 <         * A list of elements that were moved from the unvisited portion of
413 >         * A queue of elements that were moved from the unvisited portion of
414           * the heap into the visited portion as a result of "unlucky" element
415           * removals during the iteration.  (Unlucky element removals are those
416 <         * that require a fixup instead of a fixdown.)  We must visit all of
416 >         * that require a siftup instead of a siftdown.)  We must visit all of
417           * the elements in this list to complete the iteration.  We do this
418           * after we've completed the "normal" iteration.
419           *
420           * We expect that most iterations, even those involving removals,
421           * will not use need to store elements in this field.
422           */
423 <        private ArrayList<E> forgetMeNot = null;
423 >        private ArrayDeque<E> forgetMeNot = null;
424  
425          /**
426           * Element returned by the most recent call to next iff that
427           * element was drawn from the forgetMeNot list.
428           */
429 <        private Object lastRetElt = null;
429 >        private E lastRetElt = null;
430 >
431 >        /**
432 >         * The modCount value that the iterator believes that the backing
433 >         * List should have.  If this expectation is violated, the iterator
434 >         * has detected concurrent modification.
435 >         */
436 >        private int expectedModCount = modCount;
437  
438          public boolean hasNext() {
439 <            return cursor <= size || forgetMeNot != null;
439 >            return cursor < size ||
440 >                (forgetMeNot != null && !forgetMeNot.isEmpty());
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 {
478 <                int remaining = forgetMeNot.size();
479 <                result = forgetMeNot.remove(remaining - 1);
480 <                if (remaining == 1)
481 <                    forgetMeNot = null;
482 <                lastRet = 0;
483 <                lastRetElt = result;
444 >            if (expectedModCount != modCount)
445 >                throw new ConcurrentModificationException();
446 >            if (cursor < size)
447 >                return (E) queue[lastRet = cursor++];
448 >            if (forgetMeNot != null) {
449 >                lastRet = -1;
450 >                lastRetElt = forgetMeNot.poll();
451 >                if (lastRetElt != null)
452 >                    return lastRetElt;
453              }
454 <            return result;
454 >            throw new NoSuchElementException();
455          }
456  
457          public void remove() {
458 <            checkForComodification();
459 <
460 <            if (lastRet != 0) {
458 >            if (expectedModCount != modCount)
459 >                throw new ConcurrentModificationException();
460 >            if (lastRet == -1 && lastRetElt == null)
461 >                throw new IllegalStateException();
462 >            if (lastRet != -1) {
463                  E moved = PriorityQueue.this.removeAt(lastRet);
464 <                lastRet = 0;
465 <                if (moved == null) {
464 >                lastRet = -1;
465 >                if (moved == null)
466                      cursor--;
467 <                } else {
467 >                else {
468                      if (forgetMeNot == null)
469 <                        forgetMeNot = new ArrayList<E>();
469 >                        forgetMeNot = new ArrayDeque<E>();
470                      forgetMeNot.add(moved);
471                  }
501            } else if (lastRetElt != null) {
502                PriorityQueue.this.remove(lastRetElt);
503                lastRetElt = null;
472              } else {
473 <                throw new IllegalStateException();
473 >                PriorityQueue.this.removeEq(lastRetElt);
474 >                lastRetElt = null;
475              }
507
476              expectedModCount = modCount;
477          }
478  
511        final void checkForComodification() {
512            if (modCount != expectedModCount)
513                throw new ConcurrentModificationException();
514        }
479      }
480  
481      public int size() {
# Line 524 | Line 488 | public class PriorityQueue<E> extends Ab
488       */
489      public void clear() {
490          modCount++;
491 <
528 <        // Null out element references to prevent memory leak
529 <        for (int i=1; i<=size; i++)
491 >        for (int i = 0; i < size; i++)
492              queue[i] = null;
531
493          size = 0;
494      }
495  
496      public E poll() {
497          if (size == 0)
498              return null;
499 +        int s = --size;
500          modCount++;
501 <
502 <        E result = (E) queue[1];
503 <        queue[1] = queue[size];
504 <        queue[size--] = null;  // Drop extra ref to prevent memory leak
505 <        if (size > 1)
544 <            fixDown(1);
545 <
501 >        E result = (E)queue[0];
502 >        E x = (E)queue[s];
503 >        queue[s] = null;
504 >        if (s != 0)
505 >            siftDown(0, x);
506          return result;
507      }
508  
509      /**
510 <     * Removes and returns the ith element from queue.  (Recall that queue
551 <     * is one-based, so 1 <= i <= size.)
510 >     * Removes the ith element from queue.
511       *
512 <     * Normally this method leaves the elements at positions from 1 up to i-1,
513 <     * inclusive, untouched.  Under these circumstances, it returns null.
514 <     * Occasionally, in order to maintain the heap invariant, it must move
515 <     * the last element of the list to some index in the range [2, i-1],
516 <     * and move the element previously at position (i/2) to position i.
517 <     * Under these circumstances, this method returns the element that was
518 <     * previously at the end of the list and is now at some position between
519 <     * 2 and i-1 inclusive.
512 >     * Normally this method leaves the elements at up to i-1,
513 >     * inclusive, untouched.  Under these circumstances, it returns
514 >     * null.  Occasionally, in order to maintain the heap invariant,
515 >     * it must swap a later element of the list with one earlier than
516 >     * i.  Under these circumstances, this method returns the element
517 >     * that was previously at the end of the list and is now at some
518 >     * position before i. This fact is used by iterator.remove so as to
519 >     * avoid missing traverseing elements.
520       */
521      private E removeAt(int i) {
522 <        assert i > 0 && i <= size;
522 >        assert i >= 0 && i < size;
523          modCount++;
524 <
525 <        E moved = (E) queue[size];
526 <        queue[i] = moved;
527 <        queue[size--] = null;  // Drop extra ref to prevent memory leak
528 <        if (i <= size) {
529 <            fixDown(i);
524 >        int s = --size;
525 >        if (s == i) // removed last element
526 >            queue[i] = null;
527 >        else {
528 >            E moved = (E) queue[s];
529 >            queue[s] = null;
530 >            siftDown(i, moved);
531              if (queue[i] == moved) {
532 <                fixUp(i);
532 >                siftUp(i, moved);
533                  if (queue[i] != moved)
534                      return moved;
535              }
# Line 578 | Line 538 | public class PriorityQueue<E> extends Ab
538      }
539  
540      /**
541 <     * Establishes the heap invariant (described above) assuming the heap
542 <     * satisfies the invariant except possibly for the leaf-node indexed by k
543 <     * (which may have a nextExecutionTime less than its parent's).
544 <     *
545 <     * This method functions by "promoting" queue[k] up the hierarchy
546 <     * (by swapping it with its parent) repeatedly until queue[k]
547 <     * is greater than or equal to its parent.
548 <     */
549 <    private void fixUp(int k) {
550 <        if (comparator == null) {
551 <            while (k > 1) {
552 <                int j = k >> 1;
553 <                if (((Comparable<? super E>)queue[j]).compareTo((E)queue[k]) <= 0)
554 <                    break;
555 <                Object tmp = queue[j];  queue[j] = queue[k]; queue[k] = tmp;
556 <                k = j;
557 <            }
558 <        } else {
559 <            while (k > 1) {
560 <                int j = k >>> 1;
561 <                if (comparator.compare((E)queue[j], (E)queue[k]) <= 0)
562 <                    break;
563 <                Object tmp = queue[j];  queue[j] = queue[k]; queue[k] = tmp;
564 <                k = j;
565 <            }
566 <        }
567 <    }
568 <
569 <    /**
570 <     * Establishes the heap invariant (described above) in the subtree
571 <     * rooted at k, which is assumed to satisfy the heap invariant except
572 <     * possibly for node k itself (which may be greater than its children).
573 <     *
574 <     * This method functions by "demoting" queue[k] down the hierarchy
575 <     * (by swapping it with its smaller child) repeatedly until queue[k]
576 <     * is less than or equal to its children.
577 <     */
578 <    private void fixDown(int k) {
579 <        int j;
580 <        if (comparator == null) {
581 <            while ((j = k << 1) <= size && (j > 0)) {
582 <                if (j<size &&
583 <                    ((Comparable<? super E>)queue[j]).compareTo((E)queue[j+1]) > 0)
584 <                    j++; // j indexes smallest kid
585 <
586 <                if (((Comparable<? super E>)queue[k]).compareTo((E)queue[j]) <= 0)
587 <                    break;
588 <                Object tmp = queue[j];  queue[j] = queue[k]; queue[k] = tmp;
589 <                k = j;
590 <            }
591 <        } else {
592 <            while ((j = k << 1) <= size && (j > 0)) {
593 <                if (j<size &&
594 <                    comparator.compare((E)queue[j], (E)queue[j+1]) > 0)
595 <                    j++; // j indexes smallest kid
596 <                if (comparator.compare((E)queue[k], (E)queue[j]) <= 0)
597 <                    break;
598 <                Object tmp = queue[j];  queue[j] = queue[k]; queue[k] = tmp;
599 <                k = j;
600 <            }
541 >     * Inserts item x at position k, maintaining heap invariant by
542 >     * promoting x up the tree until it is greater than or equal to
543 >     * its parent, or is the root.
544 >     *
545 >     * To simplify and speed up coercions and comparisons. the
546 >     * Comparable and Comparator versions are separated into different
547 >     * methods that are otherwise identical. (Similarly for siftDown.)
548 >     *
549 >     * @param k the position to fill
550 >     * @param x the item to insert
551 >     */
552 >    private void siftUp(int k, E x) {
553 >        if (comparator != null)
554 >            siftUpUsingComparator(k, x);
555 >        else
556 >            siftUpComparable(k, x);
557 >    }
558 >
559 >    private void siftUpComparable(int k, E x) {
560 >        Comparable<? super E> key = (Comparable<? super E>) x;
561 >        while (k > 0) {
562 >            int parent = (k - 1) >>> 1;
563 >            Object e = queue[parent];
564 >            if (key.compareTo((E)e) >= 0)
565 >                break;
566 >            queue[k] = e;
567 >            k = parent;
568 >        }
569 >        queue[k] = key;
570 >    }
571 >
572 >    private void siftUpUsingComparator(int k, E x) {
573 >        while (k > 0) {
574 >            int parent = (k - 1) >>> 1;
575 >            Object e = queue[parent];
576 >            if (comparator.compare(x, (E)e) >= 0)
577 >                break;
578 >            queue[k] = e;
579 >            k = parent;
580 >        }
581 >        queue[k] = x;
582 >    }
583 >
584 >    /**
585 >     * Inserts item x at position k, maintaining heap invariant by
586 >     * demoting x down the tree repeatedly until it is less than or
587 >     * equal to its children or is a leaf.
588 >     *
589 >     * @param k the position to fill
590 >     * @param x the item to insert
591 >     */
592 >    private void siftDown(int k, E x) {
593 >        if (comparator != null)
594 >            siftDownUsingComparator(k, x);
595 >        else
596 >            siftDownComparable(k, x);
597 >    }
598 >
599 >    private void siftDownComparable(int k, E x) {
600 >        Comparable<? super E> key = (Comparable<? super E>)x;
601 >        int half = size >>> 1;        // loop while a non-leaf
602 >        while (k < half) {
603 >            int child = (k << 1) + 1; // assume left child is least
604 >            Object c = queue[child];
605 >            int right = child + 1;
606 >            if (right < size &&
607 >                ((Comparable<? super E>)c).compareTo((E)queue[right]) > 0)
608 >                c = queue[child = right];
609 >            if (key.compareTo((E)c) <= 0)
610 >                break;
611 >            queue[k] = c;
612 >            k = child;
613 >        }
614 >        queue[k] = key;
615 >    }
616 >
617 >    private void siftDownUsingComparator(int k, E x) {
618 >        int half = size >>> 1;
619 >        while (k < half) {
620 >            int child = (k << 1) + 1;
621 >            Object c = queue[child];
622 >            int right = child + 1;
623 >            if (right < size &&
624 >                comparator.compare((E)c, (E)queue[right]) > 0)
625 >                c = queue[child = right];
626 >            if (comparator.compare(x, (E)c) <= 0)
627 >                break;
628 >            queue[k] = c;
629 >            k = child;
630          }
631 +        queue[k] = x;
632      }
633  
634      /**
# Line 646 | Line 636 | public class PriorityQueue<E> extends Ab
636       * assuming nothing about the order of the elements prior to the call.
637       */
638      private void heapify() {
639 <        for (int i = size/2; i >= 1; i--)
640 <            fixDown(i);
639 >        for (int i = (size >>> 1) - 1; i >= 0; i--)
640 >            siftDown(i, (E)queue[i]);
641      }
642  
643      /**
# Line 678 | Line 668 | public class PriorityQueue<E> extends Ab
668          s.defaultWriteObject();
669  
670          // Write out array length
671 <        s.writeInt(queue.length);
671 >        // For compatibility with 1.5 version, must be at least 2.
672 >        s.writeInt(Math.max(2, queue.length));
673  
674          // Write out all elements in the proper order.
675 <        for (int i=1; i<=size; i++)
675 >        for (int i=0; i<size; i++)
676              s.writeObject(queue[i]);
677      }
678  
# Line 700 | Line 691 | public class PriorityQueue<E> extends Ab
691          queue = new Object[arrayLength];
692  
693          // Read in all elements in the proper order.
694 <        for (int i=1; i<=size; i++)
694 >        for (int i=0; i<size; i++)
695              queue[i] = (E) s.readObject();
696      }
697  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines