[cvs] / jsr166 / src / main / java / util / PriorityQueue.java Repository:
ViewVC logotype

Diff of /jsr166/src/main/java/util/PriorityQueue.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.35, Wed Aug 27 10:27:07 2003 UTC revision 1.36, Sat Aug 30 11:40:04 2003 UTC
# Line 2  Line 2 
2    
3  /**  /**
4   * An unbounded priority {@linkplain Queue queue} based on a priority heap.   * An unbounded priority {@linkplain Queue queue} based on a priority heap.
5   * This queue orders   * This queue orders elements according to an order specified at construction
6   * elements according to an order specified at construction time, which is   * time, which is specified in the same manner as {@link java.util.TreeSet}
7   * specified in the same manner as {@link java.util.TreeSet} and   * and {@link java.util.TreeMap}: elements are ordered either according to
8   * {@link java.util.TreeMap}: elements are ordered   * their <i>natural order</i> (see {@link Comparable}), or according to a
9   * either according to their <i>natural order</i> (see {@link Comparable}), or   * {@link java.util.Comparator}, depending on which constructor is used.
  * according to a {@link java.util.Comparator}, depending on which  
  * constructor is used.  
10   * <p>The <em>head</em> of this queue is the <em>least</em> element with   * <p>The <em>head</em> of this queue is the <em>least</em> element with
11   * respect to the specified ordering.   * respect to the specified ordering.  If multiple elements are tied for least
12   * If multiple elements are tied for least value, the   * value, the head is one of those elements. A priority queue does not permit
  * head is one of those elements. A priority queue does not permit  
13   * <tt>null</tt> elements.   * <tt>null</tt> elements.
14   *   *
15   * <p>The {@link #remove()} and {@link #poll()} methods remove and   * <p>The {@link #remove()} and {@link #poll()} methods remove and
# Line 150  Line 147 
147      /**      /**
148       * Initially fill elements of the queue array under the       * Initially fill elements of the queue array under the
149       * knowledge that it is sorted or is another PQ, in which       * knowledge that it is sorted or is another PQ, in which
150       * case we can just place the elements without fixups.       * case we can just place the elements in the order presented.
151       */       */
152      private void fillFromSorted(Collection<? extends E> c) {      private void fillFromSorted(Collection<? extends E> c) {
153          for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )          for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )
154              queue[++size] = i.next();              queue[++size] = i.next();
155      }      }
156    
   
157      /**      /**
158       * Initially fill elements of the queue array that is       * Initially fill elements of the queue array that is not to our knowledge
159       * not to our knowledge sorted, so we must add them       * sorted, so we must rearrange the elements to guarantee the heap
160       * one by one.       * invariant.
161       */       */
162      private void fillFromUnsorted(Collection<? extends E> c) {      private void fillFromUnsorted(Collection<? extends E> c) {
163          for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )          for (Iterator<? extends E> i = c.iterator(); i.hasNext(); )
164              add(i.next());              queue[++size] = i.next();
165            heapify();
166      }      }
167    
168      /**      /**
# Line 271  Line 268 
268          queue = newQueue;          queue = newQueue;
269      }      }
270    
     // Queue Methods  
   
271    
272        // Queue Methods
273    
274      /**      /**
275       * Add the specified element to this priority queue.       * Add the specified element to this priority queue.
# Line 302  Line 298 
298      public E poll() {      public E poll() {
299          if (size == 0)          if (size == 0)
300              return null;              return null;
301          return (E) remove(1);          return remove();
302      }      }
303    
304      public E peek() {      public E peek() {
# Line 366  Line 362 
362          if (comparator == null) {          if (comparator == null) {
363              for (int i = 1; i <= size; i++) {              for (int i = 1; i <= size; i++) {
364                  if (((Comparable<E>)queue[i]).compareTo((E)o) == 0) {                  if (((Comparable<E>)queue[i]).compareTo((E)o) == 0) {
365                      remove(i);                      removeAt(i);
366                      return true;                      return true;
367                  }                  }
368              }              }
369          } else {          } else {
370              for (int i = 1; i <= size; i++) {              for (int i = 1; i <= size; i++) {
371                  if (comparator.compare((E)queue[i], (E)o) == 0) {                  if (comparator.compare((E)queue[i], (E)o) == 0) {
372                      remove(i);                      removeAt(i);
373                      return true;                      return true;
374                  }                  }
375              }              }
# Line 400  Line 396 
396          private int cursor = 1;          private int cursor = 1;
397    
398          /**          /**
399           * Index of element returned by most recent call to next or           * Index of element returned by most recent call to next,
400           * previous.  Reset to 0 if this element is deleted by a call           * unless that element came from the forgetMeNot list.
401           * to remove.           * Reset to 0 if element is deleted by a call to remove.
402           */           */
403          private int lastRet = 0;          private int lastRet = 0;
404    
# Line 413  Line 409 
409           */           */
410          private int expectedModCount = modCount;          private int expectedModCount = modCount;
411    
412          // Workarounds until version that better handles remove() installed.          /**
413          // These are used to copy-on-write the array upon first remove           * A list of elements that were moved from the unvisited portion of
414          private Object[] q = queue;           * the heap into the visited portion as a result of "unlucky" element
415          private int qsize = size;           * removals during the iteration.  (Unlucky element removals are those
416             * that require a fixup instead of a fixdown.)  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;
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;
430    
431          public boolean hasNext() {          public boolean hasNext() {
432              return cursor <= qsize;              return cursor <= size || forgetMeNot != null;
433          }          }
434    
435          public E next() {          public E next() {
436              checkForComodification();              checkForComodification();
437              if (cursor > qsize)              E result;
438                  throw new NoSuchElementException();              if (cursor <= size) {
439              E result = (E) q[cursor];                  result = (E) queue[cursor];
440              lastRet = cursor++;              lastRet = cursor++;
441                }
442                else if (forgetMeNot == null)
443                    throw new NoSuchElementException();
444                else {
445                    int remaining = forgetMeNot.size();
446                    result = forgetMeNot.remove(remaining - 1);
447                    if (remaining == 1)
448                        forgetMeNot = null;
449                    lastRet = 0;
450                    lastRetElt = result;
451                }
452              return result;              return result;
453          }          }
454    
455          public void remove() {          public void remove() {
             if (lastRet == 0)  
                 throw new IllegalStateException();  
456              checkForComodification();              checkForComodification();
457    
458              // Copy on first remove              if (lastRet != 0) {
459              if (q == queue) {                  E moved = PriorityQueue.this.removeAt(lastRet);
460                  q = new Object[queue.length];                  lastRet = 0;
461                  System.arraycopy(queue, 0, q, 0, queue.length);                  if (moved == null) {
462                        cursor--;
463                    } else {
464                        if (forgetMeNot == null)
465                            forgetMeNot = new ArrayList();
466                        forgetMeNot.add(moved);
467                    }
468                } else if (lastRetElt != null) {
469                    PriorityQueue.this.remove(lastRetElt);
470                    lastRetElt = null;
471                } else {
472                    throw new IllegalStateException();
473              }              }
             PriorityQueue.this.remove(q[lastRet]);  
474    
             lastRet = 0;  
475              expectedModCount = modCount;              expectedModCount = modCount;
476          }          }
477    
# Line 471  Line 499 
499      }      }
500    
501      /**      /**
502       * Removes and returns the ith element from queue.  Recall       * Removes and returns the first element from queue.
503       * that queue is one-based, so 1 <= i <= size.       */
504        public E remove() {
505            if (size == 0)
506                throw new NoSuchElementException();
507            modCount++;
508    
509            E result = (E) queue[1];
510            queue[1] = queue[size];
511            queue[size--] = null;  // Drop extra ref to prevent memory leak
512            if (size > 1)
513                fixDown(1);
514    
515            return result;
516        }
517    
518        /**
519         * Removes and returns the ith element from queue.  (Recall that queue
520         * is one-based, so 1 <= i <= size.)
521       *       *
522         * Normally this method leaves the elements at positions from 1 up to i-1,
523         * inclusive, untouched.  Under these circumstances, it returns null.
524         * Occasionally, in order to maintain the heap invariant, it must move
525         * the last element of the list to some index in the range [2, i-1],
526         * and move the element previously at position (i/2) to position i.
527         * Under these circumstances, this method returns the element that was
528         * previously at the end of the list and is now at some position between
529         * 2 and i-1 inclusive.
530       */       */
531      private E remove(int i) {      private E removeAt(int i) {
532          assert i <= size;          assert i > 0 && i <= size;
533          modCount++;          modCount++;
534    
535          E result = (E) queue[i];          E moved = (E) queue[size];
536          queue[i] = queue[size];          queue[i] = moved;
537          queue[size--] = null;  // Drop extra ref to prevent memory leak          queue[size--] = null;  // Drop extra ref to prevent memory leak
538          if (i <= size) {          if (i <= size) {
539              fixDown(i);              fixDown(i);
540                if (queue[i] == moved) {
541              fixUp(i);              fixUp(i);
542                    if (queue[i] != moved)
543                        return moved;
544          }          }
545            }
546          return result;          return null;
547      }      }
548    
549      /**      /**
# Line 552  Line 608 
608                  k = j;                  k = j;
609              }              }
610          }          }
   
611      }      }
612    
613        /**
614         * Establishes the heap invariant (described above) in the entire tree,
615         * assuming nothing about the order of the elements prior to the call.
616         */
617        private void heapify() {
618            for (int i = size/2; i >= 1; i--)
619                fixDown(i);
620        }
621    
622      /**      /**
623       * Returns the comparator used to order this collection, or <tt>null</tt>       * Returns the comparator used to order this collection, or <tt>null</tt>
# Line 610  Line 673 
673      }      }
674    
675  }  }
   

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.36

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8