package edu.wlu.cs.levy.CG;
@SuppressWarnings("serial")
class PriorityQueue implements java.io.Serializable {
/**
* This class implements a <code>PriorityQueue</code>. This class is
* implemented in such a way that objects are added using an
* <code>add</code> function. The <code>add</code> function takes two
* parameters an object and a long.
* <p>
* The object represents an item in the queue, the long indicates its
* priority in the queue. The remove function in this class returns the
* object first in the queue and that object is removed from the queue
* permanently.
*
* @author Bjoern Heckel
* @version %I%, %G%
* @since JDK1.2
*/
/**
* The maximum priority possible in this priority queue.
*/
private float maxPriority = Float.MAX_VALUE;
/**
* This contains the list of objects in the queue.
*/
private Object[] data;
/**
* This contains the list of prioritys in the queue.
*/
private float[] value;
/**
* Holds the number of elements currently in the queue.
*/
private int count;
/**
* This holds the number elements this queue can have.
*/
private int capacity;
/**
* Creates a new <code>PriorityQueue</code> object. The
* <code>PriorityQueue</code> object allows objects to be entered into the
* queue and to leave in the order of priority i.e the highest priority
* get's to leave first.
*/
public PriorityQueue() {
init(20);
}
/**
* Creates a new <code>PriorityQueue</code> object. The
* <code>PriorityQueue</code> object allows objects to be entered into the
* queue an to leave in the order of priority i.e the highest priority get's
* to leave first.
*
* @param capacity
* the initial capacity of the queue before a resize
*/
public PriorityQueue(int capacity) {
init(capacity);
}
/**
* Creates a new <code>PriorityQueue</code> object. The
* <code>PriorityQueue</code> object allows objects to be entered into the
* queue an to leave in the order of priority i.e the highest priority get's
* to leave first.
*
* @param capacity
* the initial capacity of the queue before a resize
* @param maxPriority
* is the maximum possible priority for an object
*/
public PriorityQueue(int capacity, float maxPriority) {
this.maxPriority = maxPriority;
init(capacity);
}
/**
* This is an initializer for the object. It basically initializes an array
* of long called value to represent the prioritys of the objects, it also
* creates an array of objects to be used in parallel with the array of
* longs, to represent the objects entered, these can be used to sequence
* the data.
*
* @param size
* the initial capacity of the queue, it can be resized
*/
private void init(int size) {
capacity = size;
data = new Object[capacity + 1];
value = new float[capacity + 1];
value[0] = maxPriority;
data[0] = null;
}
/**
* This function adds the given object into the <code>PriorityQueue</code>,
* its priority is the long priority. The way in which priority can be
* associated with the elements of the queue is by keeping the priority and
* the elements array entrys parallel.
*
* @param element
* is the object that is to be entered into this
* <code>PriorityQueue</code>
* @param priority
* this is the priority that the object holds in the
* <code>PriorityQueue</code>
*/
public void add(Object element, float priority) {
if (count++ >= capacity) {
expandCapacity();
}
/* put this as the last element */
value[count] = priority;
data[count] = element;
bubbleUp(count);
}
/**
* Remove is a function to remove the element in the queue with the maximum
* priority. Once the element is removed then it can never be recovered from
* the queue with further calls. The lowest priority object will leave last.
*
* @return the object with the highest priority or if it's empty null
*/
public Object remove() {
if (count == 0) {
return null;
}
Object element = data[1];
/* swap the last element into the first */
data[1] = data[count];
value[1] = value[count];
/* let the GC clean up */
data[count] = null;
value[count] = 0L;
count--;
bubbleDown(1);
return element;
}
public Object front() {
return data[1];
}
public float getMaxPriority() {
return value[1];
}
/**
* Bubble down is used to put the element at subscript 'pos' into it's
* rightful place in the heap (i.e heap is another name for
* <code>PriorityQueue</code>). If the priority of an element at subscript
* 'pos' is less than it's children then it must be put under one of these
* children, i.e the ones with the maximum priority must come first.
*
* @param pos
* is the position within the arrays of the element and priority
*/
private void bubbleDown(int pos) {
Object element = data[pos];
float priority = value[pos];
int child;
/* hole is position '1' */
for (; pos * 2 <= count; pos = child) {
child = pos * 2;
/*
* if 'child' equals 'count' then there is only one leaf for this
* parent
*/
if (child != count) {
/* left_child > right_child */
if (value[child] < value[child + 1]) {
child++; /* choose the biggest child */
}
}
/*
* percolate down the data at 'pos', one level i.e biggest child
* becomes the parent
*/
if (priority < value[child]) {
value[pos] = value[child];
data[pos] = data[child];
} else {
break;
}
}
value[pos] = priority;
data[pos] = element;
}
/**
* Bubble up is used to place an element relatively low in the queue to it's
* rightful place higher in the queue, but only if it's priority allows it
* to do so, similar to bubbleDown only in the other direction this swaps
* out its parents.
*
* @param pos
* the position in the arrays of the object to be bubbled up
*/
private void bubbleUp(int pos) {
Object element = data[pos];
float priority = value[pos];
/* when the parent is not less than the child, end */
while (value[pos / 2] < priority) {
/* overwrite the child with the parent */
value[pos] = value[pos / 2];
data[pos] = data[pos / 2];
pos /= 2;
}
value[pos] = priority;
data[pos] = element;
}
/**
* This ensures that there is enough space to keep adding elements to the
* priority queue. It is however advised to make the capacity of the queue
* large enough so that this will not be used as it is an expensive method.
* This will copy across from 0 as 'off' equals 0 is contains some important
* data.
*/
private void expandCapacity() {
capacity = count * 2;
Object[] elements = new Object[capacity + 1];
float[] prioritys = new float[capacity + 1];
System.arraycopy(data, 0, elements, 0, data.length);
System.arraycopy(value, 0, prioritys, 0, data.length);
data = elements;
value = prioritys;
}
/**
* This method will empty the queue. This also helps garbage collection by
* releasing any reference it has to the elements in the queue. This starts
* from offset 1 as off equals 0 for the elements array.
*/
public void clear() {
for (int i = 1; i < count; i++) {
data[i] = null; /* help gc */
}
count = 0;
}
/**
* The number of elements in the queue. The length indicates the number of
* elements that are currently in the queue.
*
* @return the number of elements in the queue
*/
public int length() {
return count;
}
}