jaroslav@633: /* jaroslav@633: * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. jaroslav@633: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@633: * jaroslav@633: * This code is free software; you can redistribute it and/or modify it jaroslav@633: * under the terms of the GNU General Public License version 2 only, as jaroslav@633: * published by the Free Software Foundation. Oracle designates this jaroslav@633: * particular file as subject to the "Classpath" exception as provided jaroslav@633: * by Oracle in the LICENSE file that accompanied this code. jaroslav@633: * jaroslav@633: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@633: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@633: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@633: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@633: * accompanied this code). jaroslav@633: * jaroslav@633: * You should have received a copy of the GNU General Public License version jaroslav@633: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@633: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@633: * jaroslav@633: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@633: * or visit www.oracle.com if you need additional information or have any jaroslav@633: * questions. jaroslav@633: */ jaroslav@633: jaroslav@633: package java.util; jaroslav@633: jaroslav@635: jaroslav@633: /** jaroslav@633: * An unbounded priority {@linkplain Queue queue} based on a priority heap. jaroslav@633: * The elements of the priority queue are ordered according to their jaroslav@633: * {@linkplain Comparable natural ordering}, or by a {@link Comparator} jaroslav@633: * provided at queue construction time, depending on which constructor is jaroslav@633: * used. A priority queue does not permit {@code null} elements. jaroslav@633: * A priority queue relying on natural ordering also does not permit jaroslav@633: * insertion of non-comparable objects (doing so may result in jaroslav@633: * {@code ClassCastException}). jaroslav@633: * jaroslav@633: *

The head of this queue is the least element jaroslav@633: * with respect to the specified ordering. If multiple elements are jaroslav@633: * tied for least value, the head is one of those elements -- ties are jaroslav@633: * broken arbitrarily. The queue retrieval operations {@code poll}, jaroslav@633: * {@code remove}, {@code peek}, and {@code element} access the jaroslav@633: * element at the head of the queue. jaroslav@633: * jaroslav@633: *

A priority queue is unbounded, but has an internal jaroslav@633: * capacity governing the size of an array used to store the jaroslav@633: * elements on the queue. It is always at least as large as the queue jaroslav@633: * size. As elements are added to a priority queue, its capacity jaroslav@633: * grows automatically. The details of the growth policy are not jaroslav@633: * specified. jaroslav@633: * jaroslav@633: *

This class and its iterator implement all of the jaroslav@633: * optional methods of the {@link Collection} and {@link jaroslav@633: * Iterator} interfaces. The Iterator provided in method {@link jaroslav@633: * #iterator()} is not guaranteed to traverse the elements of jaroslav@633: * the priority queue in any particular order. If you need ordered jaroslav@633: * traversal, consider using {@code Arrays.sort(pq.toArray())}. jaroslav@633: * jaroslav@633: *

Note that this implementation is not synchronized. jaroslav@633: * Multiple threads should not access a {@code PriorityQueue} jaroslav@633: * instance concurrently if any of the threads modifies the queue. jaroslav@633: * Instead, use the thread-safe {@link jaroslav@633: * java.util.concurrent.PriorityBlockingQueue} class. jaroslav@633: * jaroslav@633: *

Implementation note: this implementation provides jaroslav@633: * O(log(n)) time for the enqueing and dequeing methods jaroslav@633: * ({@code offer}, {@code poll}, {@code remove()} and {@code add}); jaroslav@633: * linear time for the {@code remove(Object)} and {@code contains(Object)} jaroslav@633: * methods; and constant time for the retrieval methods jaroslav@633: * ({@code peek}, {@code element}, and {@code size}). jaroslav@633: * jaroslav@633: *

This class is a member of the jaroslav@633: * jaroslav@633: * Java Collections Framework. jaroslav@633: * jaroslav@633: * @since 1.5 jaroslav@633: * @author Josh Bloch, Doug Lea jaroslav@633: * @param the type of elements held in this collection jaroslav@633: */ jaroslav@633: public class PriorityQueue extends AbstractQueue jaroslav@633: implements java.io.Serializable { jaroslav@633: jaroslav@633: private static final long serialVersionUID = -7720805057305804111L; jaroslav@633: jaroslav@633: private static final int DEFAULT_INITIAL_CAPACITY = 11; jaroslav@633: jaroslav@633: /** jaroslav@633: * Priority queue represented as a balanced binary heap: the two jaroslav@633: * children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The jaroslav@633: * priority queue is ordered by comparator, or by the elements' jaroslav@633: * natural ordering, if comparator is null: For each node n in the jaroslav@633: * heap and each descendant d of n, n <= d. The element with the jaroslav@633: * lowest value is in queue[0], assuming the queue is nonempty. jaroslav@633: */ jaroslav@633: private transient Object[] queue; jaroslav@633: jaroslav@633: /** jaroslav@633: * The number of elements in the priority queue. jaroslav@633: */ jaroslav@633: private int size = 0; jaroslav@633: jaroslav@633: /** jaroslav@633: * The comparator, or null if priority queue uses elements' jaroslav@633: * natural ordering. jaroslav@633: */ jaroslav@633: private final Comparator comparator; jaroslav@633: jaroslav@633: /** jaroslav@633: * The number of times this priority queue has been jaroslav@633: * structurally modified. See AbstractList for gory details. jaroslav@633: */ jaroslav@633: private transient int modCount = 0; jaroslav@633: jaroslav@633: /** jaroslav@633: * Creates a {@code PriorityQueue} with the default initial jaroslav@633: * capacity (11) that orders its elements according to their jaroslav@633: * {@linkplain Comparable natural ordering}. jaroslav@633: */ jaroslav@633: public PriorityQueue() { jaroslav@633: this(DEFAULT_INITIAL_CAPACITY, null); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Creates a {@code PriorityQueue} with the specified initial jaroslav@633: * capacity that orders its elements according to their jaroslav@633: * {@linkplain Comparable natural ordering}. jaroslav@633: * jaroslav@633: * @param initialCapacity the initial capacity for this priority queue jaroslav@633: * @throws IllegalArgumentException if {@code initialCapacity} is less jaroslav@633: * than 1 jaroslav@633: */ jaroslav@633: public PriorityQueue(int initialCapacity) { jaroslav@633: this(initialCapacity, null); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Creates a {@code PriorityQueue} with the specified initial capacity jaroslav@633: * that orders its elements according to the specified comparator. jaroslav@633: * jaroslav@633: * @param initialCapacity the initial capacity for this priority queue jaroslav@633: * @param comparator the comparator that will be used to order this jaroslav@633: * priority queue. If {@code null}, the {@linkplain Comparable jaroslav@633: * natural ordering} of the elements will be used. jaroslav@633: * @throws IllegalArgumentException if {@code initialCapacity} is jaroslav@633: * less than 1 jaroslav@633: */ jaroslav@633: public PriorityQueue(int initialCapacity, jaroslav@633: Comparator comparator) { jaroslav@633: // Note: This restriction of at least one is not actually needed, jaroslav@633: // but continues for 1.5 compatibility jaroslav@633: if (initialCapacity < 1) jaroslav@633: throw new IllegalArgumentException(); jaroslav@633: this.queue = new Object[initialCapacity]; jaroslav@633: this.comparator = comparator; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Creates a {@code PriorityQueue} containing the elements in the jaroslav@633: * specified collection. If the specified collection is an instance of jaroslav@633: * a {@link SortedSet} or is another {@code PriorityQueue}, this jaroslav@633: * priority queue will be ordered according to the same ordering. jaroslav@633: * Otherwise, this priority queue will be ordered according to the jaroslav@633: * {@linkplain Comparable natural ordering} of its elements. jaroslav@633: * jaroslav@633: * @param c the collection whose elements are to be placed jaroslav@633: * into this priority queue jaroslav@633: * @throws ClassCastException if elements of the specified collection jaroslav@633: * cannot be compared to one another according to the priority jaroslav@633: * queue's ordering jaroslav@633: * @throws NullPointerException if the specified collection or any jaroslav@633: * of its elements are null jaroslav@633: */ jaroslav@633: @SuppressWarnings("unchecked") jaroslav@633: public PriorityQueue(Collection c) { jaroslav@633: if (c instanceof SortedSet) { jaroslav@633: SortedSet ss = (SortedSet) c; jaroslav@633: this.comparator = (Comparator) ss.comparator(); jaroslav@633: initElementsFromCollection(ss); jaroslav@633: } jaroslav@633: else if (c instanceof PriorityQueue) { jaroslav@633: PriorityQueue pq = (PriorityQueue) c; jaroslav@633: this.comparator = (Comparator) pq.comparator(); jaroslav@633: initFromPriorityQueue(pq); jaroslav@633: } jaroslav@633: else { jaroslav@633: this.comparator = null; jaroslav@633: initFromCollection(c); jaroslav@633: } jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Creates a {@code PriorityQueue} containing the elements in the jaroslav@633: * specified priority queue. This priority queue will be jaroslav@633: * ordered according to the same ordering as the given priority jaroslav@633: * queue. jaroslav@633: * jaroslav@633: * @param c the priority queue whose elements are to be placed jaroslav@633: * into this priority queue jaroslav@633: * @throws ClassCastException if elements of {@code c} cannot be jaroslav@633: * compared to one another according to {@code c}'s jaroslav@633: * ordering jaroslav@633: * @throws NullPointerException if the specified priority queue or any jaroslav@633: * of its elements are null jaroslav@633: */ jaroslav@633: @SuppressWarnings("unchecked") jaroslav@633: public PriorityQueue(PriorityQueue c) { jaroslav@633: this.comparator = (Comparator) c.comparator(); jaroslav@633: initFromPriorityQueue(c); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Creates a {@code PriorityQueue} containing the elements in the jaroslav@633: * specified sorted set. This priority queue will be ordered jaroslav@633: * according to the same ordering as the given sorted set. jaroslav@633: * jaroslav@633: * @param c the sorted set whose elements are to be placed jaroslav@633: * into this priority queue jaroslav@633: * @throws ClassCastException if elements of the specified sorted jaroslav@633: * set cannot be compared to one another according to the jaroslav@633: * sorted set's ordering jaroslav@633: * @throws NullPointerException if the specified sorted set or any jaroslav@633: * of its elements are null jaroslav@633: */ jaroslav@633: @SuppressWarnings("unchecked") jaroslav@633: public PriorityQueue(SortedSet c) { jaroslav@633: this.comparator = (Comparator) c.comparator(); jaroslav@633: initElementsFromCollection(c); jaroslav@633: } jaroslav@633: jaroslav@633: private void initFromPriorityQueue(PriorityQueue c) { jaroslav@633: if (c.getClass() == PriorityQueue.class) { jaroslav@633: this.queue = c.toArray(); jaroslav@633: this.size = c.size(); jaroslav@633: } else { jaroslav@633: initFromCollection(c); jaroslav@633: } jaroslav@633: } jaroslav@633: jaroslav@633: private void initElementsFromCollection(Collection c) { jaroslav@633: Object[] a = c.toArray(); jaroslav@633: // If c.toArray incorrectly doesn't return Object[], copy it. jaroslav@633: if (a.getClass() != Object[].class) jaroslav@633: a = Arrays.copyOf(a, a.length, Object[].class); jaroslav@633: int len = a.length; jaroslav@633: if (len == 1 || this.comparator != null) jaroslav@633: for (int i = 0; i < len; i++) jaroslav@633: if (a[i] == null) jaroslav@633: throw new NullPointerException(); jaroslav@633: this.queue = a; jaroslav@633: this.size = a.length; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Initializes queue array with elements from the given Collection. jaroslav@633: * jaroslav@633: * @param c the collection jaroslav@633: */ jaroslav@633: private void initFromCollection(Collection c) { jaroslav@633: initElementsFromCollection(c); jaroslav@633: heapify(); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * The maximum size of array to allocate. jaroslav@633: * Some VMs reserve some header words in an array. jaroslav@633: * Attempts to allocate larger arrays may result in jaroslav@633: * OutOfMemoryError: Requested array size exceeds VM limit jaroslav@633: */ jaroslav@633: private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; jaroslav@633: jaroslav@633: /** jaroslav@633: * Increases the capacity of the array. jaroslav@633: * jaroslav@633: * @param minCapacity the desired minimum capacity jaroslav@633: */ jaroslav@633: private void grow(int minCapacity) { jaroslav@633: int oldCapacity = queue.length; jaroslav@633: // Double size if small; else grow by 50% jaroslav@633: int newCapacity = oldCapacity + ((oldCapacity < 64) ? jaroslav@633: (oldCapacity + 2) : jaroslav@633: (oldCapacity >> 1)); jaroslav@633: // overflow-conscious code jaroslav@633: if (newCapacity - MAX_ARRAY_SIZE > 0) jaroslav@633: newCapacity = hugeCapacity(minCapacity); jaroslav@633: queue = Arrays.copyOf(queue, newCapacity); jaroslav@633: } jaroslav@633: jaroslav@633: private static int hugeCapacity(int minCapacity) { jaroslav@633: if (minCapacity < 0) // overflow jaroslav@633: throw new OutOfMemoryError(); jaroslav@633: return (minCapacity > MAX_ARRAY_SIZE) ? jaroslav@633: Integer.MAX_VALUE : jaroslav@633: MAX_ARRAY_SIZE; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Inserts the specified element into this priority queue. jaroslav@633: * jaroslav@633: * @return {@code true} (as specified by {@link Collection#add}) jaroslav@633: * @throws ClassCastException if the specified element cannot be jaroslav@633: * compared with elements currently in this priority queue jaroslav@633: * according to the priority queue's ordering jaroslav@633: * @throws NullPointerException if the specified element is null jaroslav@633: */ jaroslav@633: public boolean add(E e) { jaroslav@633: return offer(e); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Inserts the specified element into this priority queue. jaroslav@633: * jaroslav@633: * @return {@code true} (as specified by {@link Queue#offer}) jaroslav@633: * @throws ClassCastException if the specified element cannot be jaroslav@633: * compared with elements currently in this priority queue jaroslav@633: * according to the priority queue's ordering jaroslav@633: * @throws NullPointerException if the specified element is null jaroslav@633: */ jaroslav@633: public boolean offer(E e) { jaroslav@633: if (e == null) jaroslav@633: throw new NullPointerException(); jaroslav@633: modCount++; jaroslav@633: int i = size; jaroslav@633: if (i >= queue.length) jaroslav@633: grow(i + 1); jaroslav@633: size = i + 1; jaroslav@633: if (i == 0) jaroslav@633: queue[0] = e; jaroslav@633: else jaroslav@633: siftUp(i, e); jaroslav@633: return true; jaroslav@633: } jaroslav@633: jaroslav@633: public E peek() { jaroslav@633: if (size == 0) jaroslav@633: return null; jaroslav@633: return (E) queue[0]; jaroslav@633: } jaroslav@633: jaroslav@633: private int indexOf(Object o) { jaroslav@633: if (o != null) { jaroslav@633: for (int i = 0; i < size; i++) jaroslav@633: if (o.equals(queue[i])) jaroslav@633: return i; jaroslav@633: } jaroslav@633: return -1; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Removes a single instance of the specified element from this queue, jaroslav@633: * if it is present. More formally, removes an element {@code e} such jaroslav@633: * that {@code o.equals(e)}, if this queue contains one or more such jaroslav@633: * elements. Returns {@code true} if and only if this queue contained jaroslav@633: * the specified element (or equivalently, if this queue changed as a jaroslav@633: * result of the call). jaroslav@633: * jaroslav@633: * @param o element to be removed from this queue, if present jaroslav@633: * @return {@code true} if this queue changed as a result of the call jaroslav@633: */ jaroslav@633: public boolean remove(Object o) { jaroslav@633: int i = indexOf(o); jaroslav@633: if (i == -1) jaroslav@633: return false; jaroslav@633: else { jaroslav@633: removeAt(i); jaroslav@633: return true; jaroslav@633: } jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Version of remove using reference equality, not equals. jaroslav@633: * Needed by iterator.remove. jaroslav@633: * jaroslav@633: * @param o element to be removed from this queue, if present jaroslav@633: * @return {@code true} if removed jaroslav@633: */ jaroslav@633: boolean removeEq(Object o) { jaroslav@633: for (int i = 0; i < size; i++) { jaroslav@633: if (o == queue[i]) { jaroslav@633: removeAt(i); jaroslav@633: return true; jaroslav@633: } jaroslav@633: } jaroslav@633: return false; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Returns {@code true} if this queue contains the specified element. jaroslav@633: * More formally, returns {@code true} if and only if this queue contains jaroslav@633: * at least one element {@code e} such that {@code o.equals(e)}. jaroslav@633: * jaroslav@633: * @param o object to be checked for containment in this queue jaroslav@633: * @return {@code true} if this queue contains the specified element jaroslav@633: */ jaroslav@633: public boolean contains(Object o) { jaroslav@633: return indexOf(o) != -1; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Returns an array containing all of the elements in this queue. jaroslav@633: * The elements are in no particular order. jaroslav@633: * jaroslav@633: *

The returned array will be "safe" in that no references to it are jaroslav@633: * maintained by this queue. (In other words, this method must allocate jaroslav@633: * a new array). The caller is thus free to modify the returned array. jaroslav@633: * jaroslav@633: *

This method acts as bridge between array-based and collection-based jaroslav@633: * APIs. jaroslav@633: * jaroslav@633: * @return an array containing all of the elements in this queue jaroslav@633: */ jaroslav@633: public Object[] toArray() { jaroslav@633: return Arrays.copyOf(queue, size); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Returns an array containing all of the elements in this queue; the jaroslav@633: * runtime type of the returned array is that of the specified array. jaroslav@633: * The returned array elements are in no particular order. jaroslav@633: * If the queue fits in the specified array, it is returned therein. jaroslav@633: * Otherwise, a new array is allocated with the runtime type of the jaroslav@633: * specified array and the size of this queue. jaroslav@633: * jaroslav@633: *

If the queue fits in the specified array with room to spare jaroslav@633: * (i.e., the array has more elements than the queue), the element in jaroslav@633: * the array immediately following the end of the collection is set to jaroslav@633: * {@code null}. jaroslav@633: * jaroslav@633: *

Like the {@link #toArray()} method, this method acts as bridge between jaroslav@633: * array-based and collection-based APIs. Further, this method allows jaroslav@633: * precise control over the runtime type of the output array, and may, jaroslav@633: * under certain circumstances, be used to save allocation costs. jaroslav@633: * jaroslav@633: *

Suppose x is a queue known to contain only strings. jaroslav@633: * The following code can be used to dump the queue into a newly jaroslav@633: * allocated array of String: jaroslav@633: * jaroslav@633: *

jaroslav@633:      *     String[] y = x.toArray(new String[0]);
jaroslav@633: * jaroslav@633: * Note that toArray(new Object[0]) is identical in function to jaroslav@633: * toArray(). jaroslav@633: * jaroslav@633: * @param a the array into which the elements of the queue are to jaroslav@633: * be stored, if it is big enough; otherwise, a new array of the jaroslav@633: * same runtime type is allocated for this purpose. jaroslav@633: * @return an array containing all of the elements in this queue jaroslav@633: * @throws ArrayStoreException if the runtime type of the specified array jaroslav@633: * is not a supertype of the runtime type of every element in jaroslav@633: * this queue jaroslav@633: * @throws NullPointerException if the specified array is null jaroslav@633: */ jaroslav@633: public T[] toArray(T[] a) { jaroslav@633: if (a.length < size) jaroslav@633: // Make a new array of a's runtime type, but my contents: jaroslav@633: return (T[]) Arrays.copyOf(queue, size, a.getClass()); jaroslav@633: System.arraycopy(queue, 0, a, 0, size); jaroslav@633: if (a.length > size) jaroslav@633: a[size] = null; jaroslav@633: return a; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Returns an iterator over the elements in this queue. The iterator jaroslav@633: * does not return the elements in any particular order. jaroslav@633: * jaroslav@633: * @return an iterator over the elements in this queue jaroslav@633: */ jaroslav@633: public Iterator iterator() { jaroslav@633: return new Itr(); jaroslav@633: } jaroslav@633: jaroslav@633: private final class Itr implements Iterator { jaroslav@633: /** jaroslav@633: * Index (into queue array) of element to be returned by jaroslav@633: * subsequent call to next. jaroslav@633: */ jaroslav@633: private int cursor = 0; jaroslav@633: jaroslav@633: /** jaroslav@633: * Index of element returned by most recent call to next, jaroslav@633: * unless that element came from the forgetMeNot list. jaroslav@633: * Set to -1 if element is deleted by a call to remove. jaroslav@633: */ jaroslav@633: private int lastRet = -1; jaroslav@633: jaroslav@633: /** jaroslav@633: * A queue of elements that were moved from the unvisited portion of jaroslav@633: * the heap into the visited portion as a result of "unlucky" element jaroslav@633: * removals during the iteration. (Unlucky element removals are those jaroslav@633: * that require a siftup instead of a siftdown.) We must visit all of jaroslav@633: * the elements in this list to complete the iteration. We do this jaroslav@633: * after we've completed the "normal" iteration. jaroslav@633: * jaroslav@633: * We expect that most iterations, even those involving removals, jaroslav@633: * will not need to store elements in this field. jaroslav@633: */ jaroslav@633: private ArrayDeque forgetMeNot = null; jaroslav@633: jaroslav@633: /** jaroslav@633: * Element returned by the most recent call to next iff that jaroslav@633: * element was drawn from the forgetMeNot list. jaroslav@633: */ jaroslav@633: private E lastRetElt = null; jaroslav@633: jaroslav@633: /** jaroslav@633: * The modCount value that the iterator believes that the backing jaroslav@633: * Queue should have. If this expectation is violated, the iterator jaroslav@633: * has detected concurrent modification. jaroslav@633: */ jaroslav@633: private int expectedModCount = modCount; jaroslav@633: jaroslav@633: public boolean hasNext() { jaroslav@633: return cursor < size || jaroslav@633: (forgetMeNot != null && !forgetMeNot.isEmpty()); jaroslav@633: } jaroslav@633: jaroslav@633: public E next() { jaroslav@633: if (expectedModCount != modCount) jaroslav@633: throw new ConcurrentModificationException(); jaroslav@633: if (cursor < size) jaroslav@633: return (E) queue[lastRet = cursor++]; jaroslav@633: if (forgetMeNot != null) { jaroslav@633: lastRet = -1; jaroslav@633: lastRetElt = forgetMeNot.poll(); jaroslav@633: if (lastRetElt != null) jaroslav@633: return lastRetElt; jaroslav@633: } jaroslav@633: throw new NoSuchElementException(); jaroslav@633: } jaroslav@633: jaroslav@633: public void remove() { jaroslav@633: if (expectedModCount != modCount) jaroslav@633: throw new ConcurrentModificationException(); jaroslav@633: if (lastRet != -1) { jaroslav@633: E moved = PriorityQueue.this.removeAt(lastRet); jaroslav@633: lastRet = -1; jaroslav@633: if (moved == null) jaroslav@633: cursor--; jaroslav@633: else { jaroslav@633: if (forgetMeNot == null) jaroslav@633: forgetMeNot = new ArrayDeque<>(); jaroslav@633: forgetMeNot.add(moved); jaroslav@633: } jaroslav@633: } else if (lastRetElt != null) { jaroslav@633: PriorityQueue.this.removeEq(lastRetElt); jaroslav@633: lastRetElt = null; jaroslav@633: } else { jaroslav@633: throw new IllegalStateException(); jaroslav@633: } jaroslav@633: expectedModCount = modCount; jaroslav@633: } jaroslav@633: } jaroslav@633: jaroslav@633: public int size() { jaroslav@633: return size; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Removes all of the elements from this priority queue. jaroslav@633: * The queue will be empty after this call returns. jaroslav@633: */ jaroslav@633: public void clear() { jaroslav@633: modCount++; jaroslav@633: for (int i = 0; i < size; i++) jaroslav@633: queue[i] = null; jaroslav@633: size = 0; jaroslav@633: } jaroslav@633: jaroslav@633: public E poll() { jaroslav@633: if (size == 0) jaroslav@633: return null; jaroslav@633: int s = --size; jaroslav@633: modCount++; jaroslav@633: E result = (E) queue[0]; jaroslav@633: E x = (E) queue[s]; jaroslav@633: queue[s] = null; jaroslav@633: if (s != 0) jaroslav@633: siftDown(0, x); jaroslav@633: return result; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Removes the ith element from queue. jaroslav@633: * jaroslav@633: * Normally this method leaves the elements at up to i-1, jaroslav@633: * inclusive, untouched. Under these circumstances, it returns jaroslav@633: * null. Occasionally, in order to maintain the heap invariant, jaroslav@633: * it must swap a later element of the list with one earlier than jaroslav@633: * i. Under these circumstances, this method returns the element jaroslav@633: * that was previously at the end of the list and is now at some jaroslav@633: * position before i. This fact is used by iterator.remove so as to jaroslav@633: * avoid missing traversing elements. jaroslav@633: */ jaroslav@633: private E removeAt(int i) { jaroslav@633: assert i >= 0 && i < size; jaroslav@633: modCount++; jaroslav@633: int s = --size; jaroslav@633: if (s == i) // removed last element jaroslav@633: queue[i] = null; jaroslav@633: else { jaroslav@633: E moved = (E) queue[s]; jaroslav@633: queue[s] = null; jaroslav@633: siftDown(i, moved); jaroslav@633: if (queue[i] == moved) { jaroslav@633: siftUp(i, moved); jaroslav@633: if (queue[i] != moved) jaroslav@633: return moved; jaroslav@633: } jaroslav@633: } jaroslav@633: return null; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Inserts item x at position k, maintaining heap invariant by jaroslav@633: * promoting x up the tree until it is greater than or equal to jaroslav@633: * its parent, or is the root. jaroslav@633: * jaroslav@633: * To simplify and speed up coercions and comparisons. the jaroslav@633: * Comparable and Comparator versions are separated into different jaroslav@633: * methods that are otherwise identical. (Similarly for siftDown.) jaroslav@633: * jaroslav@633: * @param k the position to fill jaroslav@633: * @param x the item to insert jaroslav@633: */ jaroslav@633: private void siftUp(int k, E x) { jaroslav@633: if (comparator != null) jaroslav@633: siftUpUsingComparator(k, x); jaroslav@633: else jaroslav@633: siftUpComparable(k, x); jaroslav@633: } jaroslav@633: jaroslav@633: private void siftUpComparable(int k, E x) { jaroslav@633: Comparable key = (Comparable) x; jaroslav@633: while (k > 0) { jaroslav@633: int parent = (k - 1) >>> 1; jaroslav@633: Object e = queue[parent]; jaroslav@633: if (key.compareTo((E) e) >= 0) jaroslav@633: break; jaroslav@633: queue[k] = e; jaroslav@633: k = parent; jaroslav@633: } jaroslav@633: queue[k] = key; jaroslav@633: } jaroslav@633: jaroslav@633: private void siftUpUsingComparator(int k, E x) { jaroslav@633: while (k > 0) { jaroslav@633: int parent = (k - 1) >>> 1; jaroslav@633: Object e = queue[parent]; jaroslav@633: if (comparator.compare(x, (E) e) >= 0) jaroslav@633: break; jaroslav@633: queue[k] = e; jaroslav@633: k = parent; jaroslav@633: } jaroslav@633: queue[k] = x; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Inserts item x at position k, maintaining heap invariant by jaroslav@633: * demoting x down the tree repeatedly until it is less than or jaroslav@633: * equal to its children or is a leaf. jaroslav@633: * jaroslav@633: * @param k the position to fill jaroslav@633: * @param x the item to insert jaroslav@633: */ jaroslav@633: private void siftDown(int k, E x) { jaroslav@633: if (comparator != null) jaroslav@633: siftDownUsingComparator(k, x); jaroslav@633: else jaroslav@633: siftDownComparable(k, x); jaroslav@633: } jaroslav@633: jaroslav@633: private void siftDownComparable(int k, E x) { jaroslav@633: Comparable key = (Comparable)x; jaroslav@633: int half = size >>> 1; // loop while a non-leaf jaroslav@633: while (k < half) { jaroslav@633: int child = (k << 1) + 1; // assume left child is least jaroslav@633: Object c = queue[child]; jaroslav@633: int right = child + 1; jaroslav@633: if (right < size && jaroslav@633: ((Comparable) c).compareTo((E) queue[right]) > 0) jaroslav@633: c = queue[child = right]; jaroslav@633: if (key.compareTo((E) c) <= 0) jaroslav@633: break; jaroslav@633: queue[k] = c; jaroslav@633: k = child; jaroslav@633: } jaroslav@633: queue[k] = key; jaroslav@633: } jaroslav@633: jaroslav@633: private void siftDownUsingComparator(int k, E x) { jaroslav@633: int half = size >>> 1; jaroslav@633: while (k < half) { jaroslav@633: int child = (k << 1) + 1; jaroslav@633: Object c = queue[child]; jaroslav@633: int right = child + 1; jaroslav@633: if (right < size && jaroslav@633: comparator.compare((E) c, (E) queue[right]) > 0) jaroslav@633: c = queue[child = right]; jaroslav@633: if (comparator.compare(x, (E) c) <= 0) jaroslav@633: break; jaroslav@633: queue[k] = c; jaroslav@633: k = child; jaroslav@633: } jaroslav@633: queue[k] = x; jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Establishes the heap invariant (described above) in the entire tree, jaroslav@633: * assuming nothing about the order of the elements prior to the call. jaroslav@633: */ jaroslav@633: private void heapify() { jaroslav@633: for (int i = (size >>> 1) - 1; i >= 0; i--) jaroslav@633: siftDown(i, (E) queue[i]); jaroslav@633: } jaroslav@633: jaroslav@633: /** jaroslav@633: * Returns the comparator used to order the elements in this jaroslav@633: * queue, or {@code null} if this queue is sorted according to jaroslav@633: * the {@linkplain Comparable natural ordering} of its elements. jaroslav@633: * jaroslav@633: * @return the comparator used to order this queue, or jaroslav@633: * {@code null} if this queue is sorted according to the jaroslav@633: * natural ordering of its elements jaroslav@633: */ jaroslav@633: public Comparator comparator() { jaroslav@633: return comparator; jaroslav@633: } jaroslav@633: jaroslav@633: jaroslav@633: }