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

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

Go to download

High Performance Primitive Collections Realtime (fork of HPPC of Carrotsearch) Fundamental data structures (maps, sets, lists, stacks, queues, heaps, sorts) generated for combinations of object and primitive types to conserve JVM memory and speed up execution. The Realtime fork intend of extending collections while tweaking and optimizations to remove any dynamic allocations at runtime, and low variance execution times.

There is a newer version: 0.7.5
Show newest version
package com.carrotsearch.hppcrt.heaps;

import java.util.*;

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

  
/**
 * A Heap-based, min-priority queue of doubles.
 * 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()} . * @author Vincent Sonnier */ @javax.annotation.Generated(date = "2015-02-27T19:21:03+0100", value = "HPPC-RT generated from: DoubleHeapPriorityQueue.java") public class DoubleHeapPriorityQueue extends AbstractDoubleCollection implements DoublePriorityQueue, Cloneable { /** * Default capacity if no other capacity is given in the constructor. */ public final static int DEFAULT_CAPACITY = 16; /** * 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 double[] buffer; /** * Number of elements in the queue. */ protected int elementsCount; /** * Defines the Comparator ordering of the queue, * If null, natural ordering is used. */ protected DoubleComparator 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 */ private double currentOccurenceToBeRemoved; /** * Internal predicate for removeAll */ private final DoublePredicate removeAllOccurencesPredicate = new DoublePredicate() { @Override public final boolean apply(final double value) { if (DoubleHeapPriorityQueue.this.comparator == null) { if ((Double.doubleToLongBits(value) == Double.doubleToLongBits(DoubleHeapPriorityQueue.this.currentOccurenceToBeRemoved))) { return true; } } else { if (DoubleHeapPriorityQueue.this.comparator.compare(value, DoubleHeapPriorityQueue.this.currentOccurenceToBeRemoved) == 0) { return true; } } return false; } }; /** * Create with a Comparator, an initial capacity, and a custom buffer resizing strategy. */ public DoubleHeapPriorityQueue( DoubleComparator comp, final int initialCapacity, final ArraySizingStrategy resizer) { this.comparator = comp; assert initialCapacity >= 0 : "initialCapacity must be >= 0: " + initialCapacity; assert resizer != null; this.resizer = resizer; //1-based index buffer, assure allocation final int internalSize = resizer.round(initialCapacity); this.buffer = (new double[internalSize + 1]); 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 = DoubleHeapPriorityQueue.this.size(); obj.buffer = DoubleHeapPriorityQueue.this.buffer; } @Override public void reset(final ValueIterator obj) { // for GC sake obj.buffer = null; } }); } /** * Create with default sizing strategy and initial capacity for storing * {@value #DEFAULT_CAPACITY} elements. * * @see BoundedProportionalArraySizingStrategy */ public DoubleHeapPriorityQueue( DoubleComparator comp ) { this(comp, DoubleHeapPriorityQueue.DEFAULT_CAPACITY); } /** * Create with an initial capacity, * using the natural ordering of doubles */ public DoubleHeapPriorityQueue(final int initialCapacity) { this(null, initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * Create with a given initial capacity, using a * Comparator for ordering. * * @see BoundedProportionalArraySizingStrategy */ public DoubleHeapPriorityQueue( DoubleComparator comp, final int initialCapacity) { this(comp, initialCapacity, new BoundedProportionalArraySizingStrategy()); } /** * {@inheritDoc} *

Note : The comparison criteria for * identity test is based on * * natural ordering if no * * custom comparator is given, else it uses the {@link #comparator()} criteria. */ @Override public int removeAllOccurrences(final double e1) { this.currentOccurenceToBeRemoved = e1; return removeAll(this.removeAllOccurencesPredicate); } /** * {@inheritDoc} */ @Override public int removeAll(final DoublePredicate predicate) { //remove by position int deleted = 0; final double[] 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 HeapPriorityQueue#iterator}. * Holds a DoubleCursor cursor returning (value, index) = (double value, index the position in heap) */ public final class ValueIterator extends AbstractIterator { public final DoubleCursor cursor; private double[] buffer; private int size; public ValueIterator() { this.cursor = new DoubleCursor(); //index 0 is not used in Priority queue this.cursor.index = 0; this.size = DoubleHeapPriorityQueue.this.size(); this.buffer = DoubleHeapPriorityQueue.this.buffer; } @Override protected DoubleCursor 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} *

Note : The comparison criteria for * identity test is based on * * natural ordering if no * * custom comparator is given, else it uses the {@link #comparator()} criteria. */ @Override public boolean contains(final double element) { //1-based index final int size = this.elementsCount; final double[] buff = this.buffer; if (this.comparator == null) { for (int i = 1; i <= size; i++) { if ((Double.doubleToLongBits(element) == Double.doubleToLongBits(buff[i]))) { return true; } } //end for } else { DoubleComparator comp = this.comparator; for (int i = 1; i <= size; i++) { if (comp.compare(element, buff[i]) == 0) { 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 double[] 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 double[] 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 double into the queue. * cost: O(log(N)) for a N sized queue */ @Override public void add(final double 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 double top() { double 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 double popTop() { double 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 DoubleContainer 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 double[] buff = this.buffer; int count = this.elementsCount; for (final DoubleCursor 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 double[] buff = this.buffer; //1-based index for (int i = 1; i <= max; i++) { h = 31 * h + Internals.rehash(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. * It also realizes a trim-to- this.size() in the process. */ @Override public DoubleHeapPriorityQueue clone() { //real constructor call final DoubleHeapPriorityQueue cloned = new DoubleHeapPriorityQueue(this.comparator, this.size(), this.resizer); cloned.addAll(this); cloned.defaultValue = this.defaultValue; 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 heaps are compared as follows:
     * {@inheritDoc}
*/ @Override /* */ public boolean equals(final Object obj) { if (obj != null) { if (obj == this) { return true; } //we can only compare both DoubleHeapPriorityQueue, //that has the same comparison function reference if (obj instanceof DoubleHeapPriorityQueue) { final DoubleHeapPriorityQueue other = (DoubleHeapPriorityQueue) obj; if (other.size() != this.size()) { return false; } final int size = this.elementsCount; final double[] buffer = this.buffer; final double[] otherbuffer = other.buffer; //both heaps must have the same comparison criteria if (this.comparator == null && other.comparator == null) { for (int i = 1; i <= size; i++) { if (!(Double.doubleToLongBits(buffer[i]) == Double.doubleToLongBits(otherbuffer[i]))) { return false; } } return true; } else if (this.comparator != null && this.comparator.equals(other.comparator)) { DoubleComparator comp = this.comparator; for (int i = 1; i <= size; i++) { if (comp.compare(buffer[i], otherbuffer[i]) != 0) { return false; } } return true; } } //end if DoubleHeapPriorityQueue } return false; } /** * Ensures the internal buffer has enough free slots to store * expectedAdditions. Increases internal buffer size if needed. */ protected void ensureBufferSpace(final int expectedAdditions) { final int bufferLen = (this.buffer == null ? 0 : this.buffer.length - 1); if (this.elementsCount > bufferLen - expectedAdditions) { final int newSize = this.resizer.grow(bufferLen, this.elementsCount, expectedAdditions + 1); assert newSize >= this.elementsCount + expectedAdditions : "Resizer failed to" + " return sensible new size: " + newSize + " <= " + (this.elementsCount + expectedAdditions); final double[] newBuffer = (new double[newSize]); if (bufferLen > 0) { System.arraycopy(this.buffer, 0, newBuffer, 0, this.buffer.length); } this.buffer = newBuffer; } } /** * {@inheritDoc} */ @Override public double[] toArray(final double[] 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 doubles is used instead * */ public DoubleComparator comparator() { return this.comparator; } /** * Sink function for Comparable elements * @param k */ private void sinkComparable(int k) { final int N = this.elementsCount; final double[] buffer = this.buffer; double tmp; int child; while ((k << 1) <= N) { //get the child of k child = k << 1; if (child < N && (Double.compare(buffer[child] , buffer[child + 1]) > 0)) { child++; } if (!(Double.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 } /** * Sink function for DoubleComparator elements * @param k */ private void sinkComparator(int k) { final int N = this.elementsCount; final double[] buffer = this.buffer; double tmp; int child; DoubleComparator 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) { double tmp; int parent; final double[] buffer = this.buffer; while (k > 1 && (Double.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; } } /** * Swim function for Comparator elements * @param k */ private void swimComparator(int k) { double tmp; int parent; final double[] buffer = this.buffer; DoubleComparator 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 - 2025 Weber Informatics LLC | Privacy Policy