All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.emory.mathcs.backport.java.util.PriorityQueue Maven / Gradle / Ivy

Go to download

Statistical sampling library for use in virtdata libraries, based on apache commons math 4

There is a newer version: 5.17.0
Show newest version
/*
 * Written by Dawid Kurzyniec, on the basis of public specifications of class
 * java.util.PriorityQueue by Josh Bloch, and released to the public domain,
 * as explained at http://creativecommons.org/licenses/publicdomain
 */

package edu.emory.mathcs.backport.java.util;

import java.util.Comparator;
import java.util.SortedSet;
import java.util.Iterator;
import java.util.List;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;

/**
 * An unbounded {@linkplain Queue queue} that supports element retrieval
 * in the order of relative priority. The ordering can be defined via an
 * explicit comparator; otherwise, the natural ordering of elements is used.
 * Element at the head of the queue is always the smallest one
 * according to the given ordering.
 *
 * 

While this queue is logically * unbounded, attempted additions may fail due to resource exhaustion * (causing OutOfMemoryError). This class does not permit * null elements. A priority queue relying on {@linkplain * Comparable natural ordering} also does not permit insertion of * non-comparable objects (doing so results in * ClassCastException). * *

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

Operations on this class make no guarantees about the ordering * of elements with equal priority. If you need to enforce an * ordering, you can define custom classes or comparators that use a * secondary key to break ties in primary priority values. See * {@link edu.emory.mathcs.backport.java.util.concurrent.PriorityBlockingQueue} * for an example. * *

Implementation note: basic mutative methods (insert, offer, * remove, poll etc) have complexity O(log(n)). Parameterless inspection methods * (peek, element,isEmpty) have complexity O(1). Methods contains(Object) and * remove(Object) have complexity O(n). * * @since 1.5 * @author Dawid Kurzyniec */ public class PriorityQueue extends AbstractQueue implements java.io.Serializable { private final static long serialVersionUID = -7720805057305804111L; private final static int DEFAULT_INIT_CAPACITY = 11; private transient Object[] buffer; private int size; private final Comparator comparator; private transient int modCount; /** * Creates a PriorityQueue with the default * initial capacity (11) that orders its elements according to * their {@linkplain Comparable natural ordering}. */ public PriorityQueue() { this(DEFAULT_INIT_CAPACITY, null); } /** * Creates a PriorityQueue with the specified * initial capacity that orders its elements according to their * {@linkplain Comparable natural ordering}. * * @param initialCapacity the initial capacity for this priority queue * @throws IllegalArgumentException if initialCapacity is less * than 1 */ public PriorityQueue(int initialCapacity) { this(initialCapacity, null); } /** * Creates a PriorityQueue with the specified initial * capacity that orders its elements according to the specified * comparator. * * @param comparator the comparator used to order this priority queue. * If null then the order depends on the elements' natural * ordering. * @throws IllegalArgumentException if initialCapacity is less * than 1 */ public PriorityQueue(Comparator comparator) { this(DEFAULT_INIT_CAPACITY, comparator); } public PriorityQueue(int initialCapacity, Comparator comparator) { if (initialCapacity < 1) throw new IllegalArgumentException(); this.buffer = new Object[initialCapacity]; this.comparator = comparator; } /** * Creates a PriorityQueue containing the elements from * the specified priority queue. This priority queue has an initial * capacity of 110% of the size of the specified queue, and it is * sorted according to the same comparator as the specified queue, * or according to the natural ordering of its * elements if the specified queue is sorted according to the natural * ordering of its elements. * * @param q the queue whose elements are to be placed * into this priority queue. * @throws NullPointerException if the specified queue is null */ public PriorityQueue(PriorityQueue q) { this((Collection)q); } /** * Creates a PriorityQueue containing the elements * from the specified sorted set. This priority queue has an initial * capacity of 110% of the size of the specified set, and it is * sorted according to the same comparator as the specified set, * or according to the natural ordering of its * elements if the specified set is sorted according to the natural * ordering of its elements. * * @param s the set whose elements are to be placed * into this priority queue. * @throws NullPointerException if the specified set or any * of its elements are null */ public PriorityQueue(SortedSet s) { this((Collection)s); } /** * Creates a PriorityQueue containing the elements * in the specified collection. The priority queue has an initial * capacity of 110% of the size of the specified collection. If * the specified collection is a {@link java.util.SortedSet} or a {@link * PriorityQueue}, this priority queue will be sorted according to * the same comparator, or according to the natural ordering of its * elements if the collection is sorted according to the natural * ordering of its elements. Otherwise, this priority queue is * ordered according to the natural ordering of its elements. * * @param c the collection whose elements are to be placed * into this priority queue. * @throws ClassCastException if elements of the specified collection * cannot be compared to one another according to the priority * queue's ordering. * @throws NullPointerException if the specified collection or any * of its elements are null */ public PriorityQueue(Collection c) { int capacity = c.size(); capacity += size/10; if (capacity < 0) capacity = Integer.MAX_VALUE; else if (capacity == 0) capacity = 1; this.buffer = new Object[capacity]; if (c instanceof PriorityQueue) { PriorityQueue that = (PriorityQueue)c; this.comparator = that.comparator; this.size = that.size; System.arraycopy(that.buffer, 0, this.buffer, 0, this.size); } else if (c instanceof SortedSet) { SortedSet s = (SortedSet)c; this.comparator = s.comparator(); for (Iterator itr = s.iterator(); itr.hasNext();) { buffer[size++] = itr.next(); } } else { this.comparator = null; for (Iterator itr = c.iterator(); itr.hasNext();) { buffer[size++] = itr.next(); } for (int i=size/2; i>=0; --i) { percolateDown(i, buffer[i]); } } } /** * Returns an iterator over the elements in this queue. The * iterator does not return the elements in any particular order. * The returned iterator is a thread-safe "fast-fail" iterator * that will throw {@link java.util.ConcurrentModificationException} upon * detected interference. * * @return an iterator over the elements in this queue */ public Iterator iterator() { return new Itr(); } /** * Returns the comparator used to order the elements in this queue, * or null if this queue uses the {@linkplain Comparable * natural ordering} of its elements. * * @return the comparator used to order the elements in this queue, * or null if this queue uses the natural * ordering of its elements. */ public Comparator comparator() { return comparator; } /** * Inserts the specified element into this priority queue. * * @param o the element to add * @return true (as per the spec for {@link Queue#offer}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering * @throws NullPointerException if the specified element is null */ public boolean offer(Object o) { if (o == null) throw new NullPointerException(); if (size == buffer.length) { int newlen = buffer.length*2; if (newlen < buffer.length) { // overflow if (buffer.length == Integer.MAX_VALUE) { throw new OutOfMemoryError(); } newlen = Integer.MAX_VALUE; } Object[] newbuffer = new Object[newlen]; System.arraycopy(buffer, 0, newbuffer, 0, size); buffer = newbuffer; } modCount++; percolateUp(size++, o); return true; } /** * Retrieves, but does not remove, the head of this queue, or returns * null if this queue is empty. * * @return the head of this queue, or null if this queue is * empty */ public Object peek() { return (size == 0) ? null : buffer[0]; } /** * Retrieves and removes the head of this queue, or returns null * if this queue is empty. * * @return the head of this queue, or null if this queue is * empty */ public Object poll() { if (size == 0) return null; modCount++; Object head = buffer[0]; --size; percolateDown(0, buffer[size]); buffer[size] = null; return head; } /** * Returns the number of elements in this priority queue. * * @return the number of elements in this priority queue */ public int size() { return size; } /** * Assuming that the 'idx' element is to be overwritten, takes an element * (usually from the end of the queue) to replace 'idx' and percolates it * down the heap. */ private int percolateDown(int idx, Object e) { try { if (comparator != null) { while (true) { int c = (idx<<1)+1; if (c >= size) break; if (c+1 < size) { if (comparator.compare(buffer[c], buffer[c+1]) > 0) c++; } if (comparator.compare(e, buffer[c]) <= 0) break; buffer[idx] = buffer[c]; idx = c; } } else { Comparable ec = (Comparable)e; while (true) { int c = (idx<<1)+1; if (c >= size) break; if (c+1 < size) { if (((Comparable)buffer[c]).compareTo(buffer[c+1]) > 0) c++; } if (ec.compareTo(buffer[c]) <= 0) break; buffer[idx] = buffer[c]; idx = c; } } return idx; } finally { buffer[idx] = e; } } /** * Takes an element to be inserted into the queue, puts it at 'idx' and * percolates it up the heap. */ private int percolateUp(int idx, Object e) { try { if (comparator != null) { while (idx > 0) { int c = (idx-1)>>>1; if (comparator.compare(e, buffer[c]) >= 0) break; buffer[idx] = buffer[c]; idx = c; } return idx; } else { Comparable ce = (Comparable)e; while (idx > 0) { int c = (idx-1)>>>1; if (ce.compareTo(buffer[c]) >= 0) break; buffer[idx] = buffer[c]; idx = c; } return idx; } } finally { buffer[idx] = e; } } /** * Inserts the specified element into this priority queue. * * @param o the element to add * @return true (as per the spec for {@link Collection#add}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering * @throws NullPointerException if the specified element is null */ public boolean add(Object o) { return offer(o); } /** * Retrieves and removes the head of this queue. * * @return the head of this queue */ public Object remove() { if (size == 0) throw new NoSuchElementException(); Object head = buffer[0]; modCount++; --size; percolateDown(0, buffer[size]); buffer[size] = null; return head; } /** * Retrieves, but does not remove, the head of this queue. * * @return the head of this queue * @throws NoSuchElementException of the queue is empty */ public Object element() { if (size == 0) throw new NoSuchElementException(); return buffer[0]; } /** * Returns true if this queue contains no elements. * * @return true if this queue contains no elements */ public boolean isEmpty() { return size == 0; } /** * Returns true if this queue contains the specified element. * More formally, returns true if and only if this queue contains * at least one element e such that o.equals(e). * * @param o object to be checked for containment in this queue * @return true if this queue contains the specified element */ public boolean contains(Object o) { for (int i=0; iThe returned array will be "safe" in that no references to it are * maintained by this queue. (In other words, this method must allocate * a new array). The caller is thus free to modify the returned array. * *

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

If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to * null. * *

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

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

     *     String[] y = x.toArray(new String[0]);
* * Note that toArray(new Object[0]) is identical in function to * toArray(). * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the * same runtime type is allocated for this purpose * @return an array containing all of the elements in this queue * @throws ArrayStoreException if the runtime type of the specified array * is not a supertype of the runtime type of every element in * this queue * @throws NullPointerException if the specified array is null */ public Object[] toArray(Object[] a) { if (a.length < size) { return Arrays.copyOf(buffer, size, a.getClass()); } else { System.arraycopy(buffer, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } } /** * Removes a single instance of the specified element from this queue, * if it is present. * Returns true if this queue contained the specified element * (or equivalently, if this queue changed as a result of the call). * * @param o element to be removed from this queue, if present * @return true if this queue changed as a result of the call */ public boolean remove(Object o) { if (o == null) return false; if (comparator != null) { for (int i = 0; i < size; i++) { if (comparator.compare(buffer[i], o) == 0) { removeAt(i); return true; } } } else { for (int i = 0; i < size; i++) { if (((Comparable)buffer[i]).compareTo(o) == 0) { removeAt(i); return true; } } } return false; } private Object removeAt(int i) { assert (i < size); modCount++; --size; int newpos; Object e = buffer[size]; buffer[size] = null; // first, try percolating down newpos = percolateDown(i, e); if (newpos != i) return null; // not moved; so percolate up newpos = percolateUp(i, e); return (newpos < i ? e : null); } /** * Removes all of the elements from this queue. * The queue will be empty after this call returns. */ public void clear() { modCount++; Arrays.fill(buffer, 0, size, null); size = 0; } private class Itr implements Iterator { int cursor = 0; List percolatedElems; int cursorPercolated = 0; int expectedModCount = modCount; int lastRet; Object lastRetPercolated; Itr() {} public boolean hasNext() { return cursor < size || percolatedElems != null; } public Object next() { checkForComodification(); if (cursor < size) { lastRet = cursor++; return buffer[lastRet]; } else if (percolatedElems != null) { lastRet = -1; lastRetPercolated = percolatedElems.remove(percolatedElems.size()-1); if (percolatedElems.isEmpty()) { percolatedElems = null; } return lastRetPercolated; } else { throw new NoSuchElementException(); } } public void remove() { if (lastRet >= 0) { Object percolatedElem = removeAt(lastRet); lastRet = -1; if (percolatedElem == null) { cursor--; } else { if (percolatedElems == null) percolatedElems = new ArrayList(); percolatedElems.add(percolatedElem); } } else if (lastRetPercolated != null) { PriorityQueue.this.remove(lastRetPercolated); lastRetPercolated = null; } else { throw new IllegalStateException(); } expectedModCount = modCount; } private void checkForComodification() { if (expectedModCount != modCount) { throw new ConcurrentModificationException(); } } } /** * @serialData the length of the array (queue capacity) is stored, followed * by all of its elements (as Objects) */ private void writeObject(java.io.ObjectOutputStream os) throws java.io.IOException { os.defaultWriteObject(); os.writeInt(buffer.length); for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy