/*******************************************************************************
* Copyright 2014 Analog Devices, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/
package com.analog.lyric.collect;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.jdt.annotation.Nullable;
/**
* Priority queue supporting dynamically changeable priorities of type double.
* <p>
* Unlike {@link java.util.PriorityQueue}, the priorities are stored separately
* from the elements and ordering is based directly on the double values with
* no intervening comparator. An element with the lowest value will be at the
* head of the queue.
* <p>
* @author Christopher Barber
* @since 0.05
*/
public interface IHeap<E> extends Collection<E>, Cloneable
{
/*------------------
* Internal classes
*/
/**
* Interface for {@link IHeap} entry.
* @since 0.05
*/
public interface IEntry<E> extends Cloneable
{
/**
* Returns a shallow copy of this entry.
*/
public IEntry<E> clone();
/**
* Returns non-null element contained in this entry. The element
* is guaranteed to not change as long as entry {@link #isOwned()}.
*/
public E getElement();
/**
* Priority of this entry, which may change.
* @see IHeap#changePriority(IEntry, double)
*/
public double getPriority();
/**
* True if entry is currently a member of a queue.
*/
public boolean isOwned();
}
/*--------------
* Construction
*/
/**
* Returns a copy of the queue, cloning all of its entries.
*/
public IHeap<E> clone();
/*---------------
* Local methods
*/
/**
* Change priority of given entry in queue.
* <p>
* When changing more than half of the priorities in bulk, it may
* be more efficient to defer reordering.
* <p>
* @return false if entry was not in the queue.
* @see #deferOrdering(boolean)
*
* @throws IllegalArgumentException if priority is not a number.
*/
public boolean changePriority(IEntry<E> entry, double priority);
/**
* True if entry is contained in this queue.
*/
public boolean containsEntry(IEntry<E> entry);
/**
* If true, then operations that might affect the order of the queue will not
* cause it to be reordered until required by some operation such as {@link #peek()}
* or {@link #poll()}, after which this attribute will automatically be set to false.
* <p>
* Implementations are not required to implement deferral.
* <p>
* @see #deferOrdering(boolean)
* @see #isOrdered()
*/
public boolean deferOrdering();
/**
* Defers or undefers ordering of queue.
* <p>
* When set to true and the implementation supports it, reordering of the queue will be
* deferred until the invocation of the first method that requires it, namely one of the
* peek or poll methods or this method with {@code defer}
* set to false. When supported, this will lead to faster amortized reordering when making
* bulk changes affecting the majority of the entries in the queue.
* <p>
* When set to false, the queue will immediately be ordered.
* <p>
* @return true if value of attribute was set to specified value. Will always return false if {@code defer}
* is true and implementation does not support deferral.
* @see #deferOrderingForBulkAdd
* @see #deferOrderingForBulkChange
*/
public boolean deferOrdering(boolean defer);
/**
* Defer ordering given {@code n} entries to be added to the queue.
* <p>
* Invokes {@link #deferOrdering(boolean)} if {@code n} is large enough to
* expect an amortized performance benefit.
* <p>
* @param n is the number of entries the caller intends to add to the queue.
* @return true if {@link #deferOrdering()} was enabled.
*/
public boolean deferOrderingForBulkAdd(int n);
/**
* Defer ordering given {@code n} entries to change their priorities.
* <p>
* Invokes {@link #deferOrdering(boolean)} if {@code n} is large enough to
* expect an amortized performance benefit.
* <p>
* @param n is the number of entries the caller intends to invoke {@link #changePriority(IEntry, double)} on.
* @return true if {@link #deferOrdering()} was enabled.
*/
public boolean deferOrderingForBulkChange(int n);
/**
* Return an entry containing given element, not necessarily the one
* with the lowest priority, or else null.
* <p>
* Assume O({@link #size}) time complexity unless implementation documents
* otherwise.
*/
public @Nullable IEntry<E> entryForElement(@Nullable Object element);
/**
* Ensure that queue has sufficient capacity for the specified number of elements.
* <p>
* For some implementations, calling this before adding many elements can avoid the
* cost of incrementally growing the capacity as elements are added.
*/
public void ensureCapacity(int capacity);
/**
* Returns an iterator over the heap entries not necessarily in heap order.
*/
public Iterator<? extends IEntry<E>> entryIterator();
/**
* Is queue currently in correct partial order.
* <p>
* This should only be false if {@link #deferOrdering()} is true.
*/
public boolean isOrdered();
/**
* Destructively merges contents of {@code other} heap into this one.
* <p>
* Removes all elements from {@code other} and adds them to this heap. Underlying
* entries will only be transferred if class of {@code other} is compatible with
* this class (typically meaning it is the same class).
* <p>
* @return true if entry objects were transferred.
*/
public boolean merge(IHeap<E> other);
/**
* Adds instance of {@code element} to the queue with given {@code priority} and
* returns the entry created for it, which may be used to relatively efficiently
* remove it or change its priority. Unless the implementation does not support it,
* the same element may be added multiple times with different priorities.
*
* @throws IllegalArgumentException if priority is not a number.
*/
public IEntry<E> offer(E element, double priority) throws IllegalArgumentException;
/**
* Returns element that will be returned by {@link #poll()} without removing it from the queue.
* <p>
* @see #peekEntry()
* @see #poll()
*/
public @Nullable E peek();
/**
* Returns entry that will be returned by {@link #pollEntry()} without removing it from the queue.
* <p>
* @see #peek()
* @see #pollEntry()
*/
public @Nullable IEntry<E> peekEntry();
/**
* Removes element with the lowest priority from the queue.
* <p>
* @see #pollEntry()
* @see #peek()
*/
public @Nullable E poll();
/**
* Removes and returns entry with the lowest priority from the queue.
* <p>
* @see #poll()
* @see #peekEntry()
*/
public @Nullable IEntry<E> pollEntry();
/**
* Remove given entry from queue.
* @return false if entry was not contained in the queue.
*/
public boolean removeEntry(IEntry<E> entry);
}