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

com.carrotsearch.hppcrt.heaps.LongHeapPriorityQueue Maven / Gradle / Ivy

Go to download

High Performance Primitive Collections Realtime (fork of HPPC from Carrotsearch) Fundamental data structures (maps, sets, lists, queues, heaps, sorts) generated for combinations of object and primitive types to conserve JVM memory and speed up execution. The Realtime fork intends to extend the existing collections, by tweaking to remove any dynamic allocations at runtime, and to obtain low variance execution times whatever the input nature.

The newest version!
package com.carrotsearch.hppcrt.heaps;

import java.util.*;

import com.carrotsearch.hppcrt.*;
import com.carrotsearch.hppcrt.cursors.*;
import com.carrotsearch.hppcrt.hash.BitMixer;
import com.carrotsearch.hppcrt.predicates.*;
import com.carrotsearch.hppcrt.procedures.*;
import com.carrotsearch.hppcrt.strategies.*;

  
/**
 * A Heap-based, min-priority queue of longs.
 * i.e. top() is the smallest element,
 * as defined by Sedgewick: Algorithms 4th Edition (2011).
 * It assure O(log(N)) complexity for insertion,  deletion and update priority of the min element,
 * and constant time to examine the min element by {@link #top()}.
 * 

Important: * Ordering of elements must be defined either * * by natural ordering * * or by a custom comparator provided in constructors, * see {@link #comparator()} . */ @javax.annotation.Generated( date = "2017-07-11T19:16:22+0200", value = "KTypeHeapPriorityQueue.java") public class LongHeapPriorityQueue extends AbstractLongCollection implements LongPriorityQueue, Cloneable { /** * Internal array for storing the priority queue. *

* Direct priority queue iteration: iterate buffer[i] for i in [1; size()] (included) but is out-of-order w.r.t {@link #popTop()} *

*/ public long [] buffer; /** * Number of elements in the queue. */ protected int elementsCount; /** * Defines the Comparator ordering of the queue, * If null, natural ordering is used. */ protected LongComparator comparator; /** * Buffer resizing strategy. */ protected final ArraySizingStrategy resizer; /** * internal pool of ValueIterator (must be created in constructor) */ protected final IteratorPool valueIteratorPool; /** * The current value set for removeAll */ protected long currentOccurenceToBeRemoved; /** * Internal predicate for removeAll */ protected LongPredicate removeAllOccurencesPredicate = new LongPredicate() { @Override public final boolean apply(final long value) { if (((value) == (LongHeapPriorityQueue.this.currentOccurenceToBeRemoved))) { return true; } return false; } }; /** * Default value returned when specified * in methods. * @see #top() */ protected long defaultValue; /** * Create with a Comparator, an initial capacity, and a custom buffer resizing strategy. */ public LongHeapPriorityQueue( LongComparator comp, final int initialCapacity, final ArraySizingStrategy resizer) { this.comparator = comp; assert resizer != null; this.resizer = resizer; //1-based index buffer, assure allocation ensureBufferSpace(Math.max(Containers.DEFAULT_EXPECTED_ELEMENTS, initialCapacity)); this.valueIteratorPool = new IteratorPool(new ObjectFactory() { @Override public ValueIterator create() { return new ValueIterator(); } @Override public void initialize(final ValueIterator obj) { obj.cursor.index = 0; obj.size = LongHeapPriorityQueue.this.size(); obj.buffer = ((LongHeapPriorityQueue.this.buffer)); } @Override public void reset(final ValueIterator obj) { // for GC sake obj.buffer = null; } }); } /** * Create with default sizing strategy and initial capacity * ({@link Containers#DEFAULT_EXPECTED_ELEMENTS}) * using a specific Comparator. * * @see BoundedProportionalArraySizingStrategy */ public LongHeapPriorityQueue( LongComparator comp ) { this(comp, Containers.DEFAULT_EXPECTED_ELEMENTS); } /** * Default constructor: create with a default * numbers of elements ({@link Containers#DEFAULT_EXPECTED_ELEMENTS}), * using the natural ordering of longs. */ public LongHeapPriorityQueue() { this(null, Containers.DEFAULT_EXPECTED_ELEMENTS); } /** * Create with an initial capacity, * using the natural ordering of longs */ public LongHeapPriorityQueue(final int initialCapacity) { this(null, initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Create with a given initial capacity, using a * Comparator for ordering. * * @see BoundedProportionalArraySizingStrategy */ public LongHeapPriorityQueue( LongComparator comp, final int initialCapacity) { this(comp, initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Creates a new heap from elements of another container. */ public LongHeapPriorityQueue(final LongContainer container) { this(container.size()); addAll(container); } /** * Create a heap from elements of another container (constructor shortcut) */ public static/* */ LongHeapPriorityQueue from(final LongContainer container) { return new LongHeapPriorityQueue(container); } /** * Create a heap from a variable number of arguments or an array of * long. */ public static/* */ LongHeapPriorityQueue from(final long... elements) { final LongHeapPriorityQueue heap = new LongHeapPriorityQueue(elements.length); for (final long elem : elements) { heap.add(elem); } return heap; } /** * {@inheritDoc} */ @Override public int removeAll(final long e1) { this.currentOccurenceToBeRemoved = e1; return removeAll(this.removeAllOccurencesPredicate); } /** * {@inheritDoc} */ @Override public int removeAll(final LongPredicate predicate) { //remove by position int deleted = 0; final long[] buffer = ((this.buffer)); int elementsCount = this.elementsCount; //1-based index int pos = 1; try { while (pos <= elementsCount) { //delete it if (predicate.apply(buffer[pos])) { //put the last element at position pos, like in deleteIndex() buffer[pos] = buffer[elementsCount]; //for GC //Diminish size elementsCount--; deleted++; } //end if to delete else { pos++; } } //end while } finally { this.elementsCount = elementsCount; //reestablish heap updatePriorities(); } return deleted; } /** * {@inheritDoc} */ @Override public void clear() { this.elementsCount = 0; } /** * An iterator implementation for {@link LongHeapPriorityQueue#iterator}. * Holds a LongCursor returning (value, index) = (long value, index the position in heap {@link LongHeapPriorityQueue#buffer}.) */ public final class ValueIterator extends AbstractIterator { public final LongCursor cursor; private long[] buffer; private int size; public ValueIterator() { this.cursor = new LongCursor(); //index 0 is not used in Priority queue this.cursor.index = 0; this.size = LongHeapPriorityQueue.this.size(); this.buffer = ((LongHeapPriorityQueue.this.buffer)); } @Override protected LongCursor fetch() { //priority is 1-based index if (this.cursor.index == this.size) { return done(); } this.cursor.value = this.buffer[++this.cursor.index]; return this.cursor; } } /** * {@inheritDoc} */ @Override public ValueIterator iterator() { //return new ValueIterator(buffer, size()); return this.valueIteratorPool.borrow(); } /** * {@inheritDoc} */ @Override public boolean contains(final long element) { //1-based index final int size = this.elementsCount; final long[] buff = ((this.buffer)); for (int i = 1; i <= size; i++) { if (((element) == (buff[i]))) { return true; } } //end for return false; } /** * {@inheritDoc} */ @Override public int size() { return this.elementsCount; } /** * {@inheritDoc} */ @Override public int capacity() { return this.buffer.length - 1; } /** * {@inheritDoc} */ @Override public T forEach(final T procedure) { final long[] buff = ((this.buffer)); final int size = this.elementsCount; for (int i = 1; i <= size; i++) { procedure.apply(buff[i]); } return procedure; } /** * {@inheritDoc} */ @Override public T forEach(final T predicate) { final long[] buff = ((this.buffer)); final int size = this.elementsCount; for (int i = 1; i <= size; i++) { if (!predicate.apply(buff[i])) { break; } } return predicate; } /** * Insert a long into the queue. * cost: O(log(N)) for a N sized queue */ @Override public void add(final long element) { ensureBufferSpace(1); //add at the end this.elementsCount++; this.buffer[this.elementsCount] = element; //swim last element swim(this.elementsCount); } /** * {@inheritDoc} * cost: O(1) */ @Override public long top() { long elem = this.defaultValue; if (this.elementsCount > 0) { elem = ((this.buffer[1])); } return elem; } /** * {@inheritDoc} * cost: O(log(N)) for a N sized queue */ @Override public long popTop() { long elem = this.defaultValue; if (this.elementsCount > 0) { elem = ((this.buffer[1])); if (this.elementsCount == 1) { //for GC //diminish size this.elementsCount = 0; } else { //at least 2 elements //put the last element in first position this.buffer[1] = this.buffer[this.elementsCount]; //for GC //diminish size this.elementsCount--; //percolate down the first element sink(1); } } return elem; } /** * Adds all elements from another container. * cost: O(N*log(N)) for N elements */ public int addAll(final LongContainer container) { return addAll((Iterable) container); } /** * Adds all elements from another iterable. * cost: O(N*log(N)) for N elements */ public int addAll(final Iterable iterable) { int size = 0; final long[] buff = ((this.buffer)); int count = this.elementsCount; for (final LongCursor cursor : iterable) { ensureBufferSpace(1); count++; buff[count] = cursor.value; size++; } this.elementsCount = count; //restore heap updatePriorities(); return size; } /** * {@inheritDoc} */ @Override public int hashCode() { int h = 1; final int max = this.elementsCount; final long[] buff = ((this.buffer)); //1-based index for (int i = 1; i <= max; i++) { h = 31 * h + BitMixer.mix(buff[i]); } return h; } /** * {@inheritDoc} * cost: O(n*log(N)) */ @Override public void updatePriorities() { if (this.comparator == null) { for (int k = this.elementsCount >> 1; k >= 1; k--) { sinkComparable(k); } } else { for (int k = this.elementsCount >> 1; k >= 1; k--) { sinkComparator(k); } } } /** * {@inheritDoc} * cost: O(log(N)) */ @Override public void updateTopPriority() { //only attempt to sink if there is at least 2 elements.... if (this.elementsCount > 1) { sink(1); } } /** * Clone this object. The returned clone will use the same resizing strategy and comparator. */ @Override public LongHeapPriorityQueue clone() { //real constructor call, of a place holder final LongHeapPriorityQueue cloned = new LongHeapPriorityQueue(this.comparator, Containers.DEFAULT_EXPECTED_ELEMENTS, this.resizer); //clone raw buffers cloned.buffer = this.buffer.clone(); cloned.defaultValue = this.defaultValue; cloned.elementsCount = this.elementsCount; return cloned; } /** * this instance and obj can only be equal to this if either:
     * (both don't have set comparators)
     * or
     * (both have equal comparators defined by {@link #comparator()}.equals(obj.comparator))
* then, both heap elements are compared with {@link #equals(Object)} iterating their {@link #buffer}. */ @Override /* */ public boolean equals(final Object obj) { if (obj != null) { if (obj == this) { return true; } //we can only compare both LongHeapPriorityQueue and not subclasses between themselves //that has the same comparison function reference if (obj.getClass() != this.getClass()) { return false; } final LongHeapPriorityQueue other = (LongHeapPriorityQueue) obj; if (other.size() != this.size()) { return false; } //If one comparator is null, and the other not, we cannot compare them, same if //both comparators are different because the heap behavior will be different, even elements are equal. if (!((this.comparator == null && other.comparator == null) || (this.comparator != null && this.comparator.equals(other.comparator)))) { return false; } final ValueIterator it = this.iterator(); final ValueIterator itOther = other.iterator(); while (it.hasNext()) { final long myVal = it.next().value; final long otherVal = itOther.next().value; if (!((myVal) == (otherVal))) { //recycle it.release(); itOther.release(); return false; } } //end while itOther.release(); return true; } return false; } /** * Ensures the internal buffer has enough free slots to store * expectedAdditions. Increases internal buffer size if needed. */ @SuppressWarnings("boxing") protected void ensureBufferSpace(final int expectedAdditions) { final int bufferLen = this.buffer == null ? 0 : this.buffer.length; //element of index 0 is not used if (this.elementsCount + 1 > bufferLen - expectedAdditions) { int newSize = this.resizer.grow(bufferLen, this.elementsCount, expectedAdditions); //first allocation, reserve an additional slot because index 0 is not used if (this.buffer == null) { newSize++; } try { final long[] newBuffer = (new long[(newSize)]); if (bufferLen > 0) { System.arraycopy(this.buffer, 0, newBuffer, 0, this.buffer.length); } this.buffer = newBuffer; } catch (final OutOfMemoryError e) { throw new BufferAllocationException( "Not enough memory to allocate buffers to grow from %d -> %d elements", e, bufferLen, newSize); } } } /** * {@inheritDoc} */ @Override public long[] toArray(final long[] target) { //copy from index 1 System.arraycopy(this.buffer, 1, target, 0, this.elementsCount); return target; } /** * Get the custom comparator used for comparing elements * @return null if no custom comparator was set, i.e natural ordering * of longs is used instead * */ public LongComparator comparator() { return this.comparator; } /** * Returns the "default value" value used * in methods returning "default value" */ @Override public long getDefaultValue() { return this.defaultValue; } /** * Set the "default value" value to be used * in methods returning "default value" */ @Override public void setDefaultValue(final long defaultValue) { this.defaultValue = defaultValue; } /** * Sink function for Comparable elements * * @param k */ private void sinkComparable(int k) { final int N = this.elementsCount; final long[] buffer = ((this.buffer)); long tmp; int child; while ((k << 1) <= N) { //get the child of k child = k << 1; if (child < N && ((buffer[child]) > (buffer[child + 1]))) { child++; } if (!((buffer[k]) > (buffer[child]))) { break; } //swap k and child tmp = buffer[k]; buffer[k] = buffer[child]; buffer[child] = tmp; k = child; } //end while } /** * Sink function for LongComparator elements * * @param k */ private void sinkComparator(int k) { final int N = this.elementsCount; final long[] buffer = ((this.buffer)); long tmp; int child; LongComparator comp = this.comparator; while ((k << 1) <= N) { //get the child of k child = k << 1; if (child < N && comp.compare(buffer[child], buffer[child + 1]) > 0) { child++; } if (comp.compare(buffer[k], buffer[child]) <= 0) { break; } //swap k and child tmp = buffer[k]; buffer[k] = buffer[child]; buffer[child] = tmp; k = child; } //end while } /** * Swim function for Comparable elements * * @param k */ private void swimComparable(int k) { long tmp; int parent; final long[] buffer = ((this.buffer)); while (k > 1 && ((buffer[k >> 1]) > (buffer[k]))) { //swap k and its parent parent = k >> 1; tmp = buffer[k]; buffer[k] = buffer[parent]; buffer[parent] = tmp; k = parent; } } /** * Swim function for Comparator elements * * @param k */ private void swimComparator(int k) { long tmp; int parent; final long[] buffer = ((this.buffer)); LongComparator comp = this.comparator; while (k > 1 && comp.compare(buffer[k >> 1], buffer[k]) > 0) { //swap k and its parent parent = k >> 1; tmp = buffer[k]; buffer[k] = buffer[parent]; buffer[parent] = tmp; k = parent; } } private void swim(final int k) { if (this.comparator == null) { swimComparable(k); } else { swimComparator(k); } } private void sink(final int k) { if (this.comparator == null) { sinkComparable(k); } else { sinkComparator(k); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy