package speiger.src.collections.PACKAGE.queues; import java.util.Arrays; import java.util.NoSuchElementException; #if TYPE_OBJECT import java.util.Comparator; import java.util.function.Consumer; #endif import java.util.Objects; import speiger.src.collections.PACKAGE.collections.COLLECTION; import speiger.src.collections.PACKAGE.collections.ITERATOR; #if !TYPE_OBJECT import speiger.src.collections.PACKAGE.functions.COMPARATOR; import speiger.src.collections.PACKAGE.functions.CONSUMER; #endif import speiger.src.collections.PACKAGE.functions.consumer.BI_OBJECT_CONSUMER; import speiger.src.collections.PACKAGE.functions.function.PREDICATE; import speiger.src.collections.PACKAGE.utils.ARRAYS; /** * A Array Priority Queue, this is a very unoptimized implementation of the PriorityQueue for very specific usecases. * It allows for duplicated entries and works like {@link java.util.List#indexOf(Object)} search. * It is highly suggested to use HeapPriorityQueue otherwise, unless you know why you need this specific implementation * @Type(T) */ public class ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE implements PRIORITY_QUEUE KEY_GENERIC_TYPE { /** The Backing Array */ protected transient KEY_TYPE[] array = EMPTY_KEY_ARRAY; /** The Amount of elements stored within the array */ protected int size; /** The Last known first index pointer */ protected int firstIndex = -1; /** The Sorter of the Array */ protected COMPARATOR KEY_SUPER_GENERIC_TYPE comparator; /** * Default Constructor */ public ARRAY_PRIORITY_QUEUE() { this(0, null); } /** * Constructor using custom sorter * @param comp Comparator to sort the Array. Can be null */ public ARRAY_PRIORITY_QUEUE(COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { this(0, comp); } /** * Constructor with a Min Capacity * @param size the initial capacity of the backing array * @throws IllegalStateException if the initial size is smaller 0 */ public ARRAY_PRIORITY_QUEUE(int size) { this(size, null); } /** * Constructor with a Min Capacity and custom Sorter * @param size the initial capacity of the backing array * @param comp Comparator to sort the Array. Can be null * @throws IllegalStateException if the initial size is smaller 0 */ public ARRAY_PRIORITY_QUEUE(int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { if(size < 0) throw new IllegalAccessError("Size has to be 0 or positive"); if(size > 0) array = NEW_KEY_ARRAY(size); this.size = size; comparator = comp; } /** * Constructor using a initial array * @param array the Array that should be used */ public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array) { this(array, array.length); } /** * Constructor using a initial array * @param array the Array that should be used * @param size the amount of elements found within the array * @throws NegativeArraySizeException if size is smaller then 0 */ public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array, int size) { this.array = Arrays.copyOf(array, size); this.size = size; } /** * Constructor using a initial array and a custom sorter * @param array the Array that should be used * @param comp Comparator to sort the Array. Can be null */ public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { this(array, array.length, comp); } /** * Constructor using a initial array and a custom sorter * @param array the Array that should be used * @param size the amount of elements found within the array * @param comp Comparator to sort the Array. Can be null * @throws NegativeArraySizeException if size is smaller then 0 */ public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { this.array = Arrays.copyOf(array, size); this.size = size; this.comparator = comp; } /** * Constructor using a Collection * @param c the Collection that should be used */ public ARRAY_PRIORITY_QUEUE(COLLECTION KEY_GENERIC_TYPE c) { array = CAST_KEY_ARRAY c.TO_ARRAY(); size = c.size(); } /** * Constructor using a Collection and a custom sorter * @param c the Collection that should be used * @param comp Comparator to sort the Array. Can be null */ public ARRAY_PRIORITY_QUEUE(COLLECTION KEY_GENERIC_TYPE c, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { array = CAST_KEY_ARRAY c.TO_ARRAY(); size = c.size(); comparator = comp; } /** * Wrapping method to help serialization * @param array the array that should be used * @Type(T) * @return a ArrayPriorityQueue containing the original input array */ public static GENERIC_KEY_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array) { return wrap(array, array.length); } /** * Wrapping method to help serialization * @param array the array that should be used * @param size the amount of elements within the array * @Type(T) * @return a ArrayPriorityQueue containing the original input array */ public static GENERIC_KEY_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, int size) { ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE queue = new ARRAY_PRIORITY_QUEUEBRACES(); queue.array = array; queue.size = size; return queue; } /** * Wrapping method to help serialization, using a custom sorter * @param array the array that should be used * @param comp Comparator to sort the Array. Can be null * @Type(T) * @return a ArrayPriorityQueue containing the original input array */ public static GENERIC_KEY_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { return wrap(array, array.length, comp); } /** * Wrapping method to help serialization, using a custom sorter * @param array the array that should be used * @param size the amount of elements within the array * @param comp Comparator to sort the Array. Can be null * @Type(T) * @return a ArrayPriorityQueue containing the original input array */ public static GENERIC_KEY_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) { ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE queue = new ARRAY_PRIORITY_QUEUEBRACES(comp); queue.array = array; queue.size = size; return queue; } @Override public void enqueue(KEY_TYPE e) { if(size == array.length) array = Arrays.copyOf(array, size+1); if(firstIndex != -1){ int compare = comparator == null ? COMPAREABLE_TO_KEY(e, array[firstIndex]) : comparator.compare(e, array[firstIndex]); if(compare < 0) firstIndex = size; else if(compare > 0) firstIndex = -1; } array[size++] = e; } @Override public KEY_TYPE dequeue() { if(size <= 0) throw new NoSuchElementException(); int index = findFirstIndex(); KEY_TYPE value = array[index]; if(index != --size) System.arraycopy(array, index+1, array, index, size - index); #if TYPE_OBJECT array[size] = null; #endif firstIndex = -1; return value; } @Override public KEY_TYPE peek(int index) { if(index < 0 || index >= size) throw new NoSuchElementException(); return array[index]; } @Override public boolean removeFirst(KEY_TYPE e) { for(int i = 0;i=0;i--) if(KEY_EQUALS(e, array[i])) return removeIndex(i); return false; } protected boolean removeIndex(int index) { if(index != --size) System.arraycopy(array, index+1, array, index, size - index); #if TYPE_OBJECT array[size] = null; #endif if(index == firstIndex) firstIndex = -1; else if(firstIndex != -1 && index >= firstIndex) firstIndex--; return true; } @Override public void onChanged() { firstIndex = -1; } @Override public int size() { return size; } @Override public void clear() { #if TYPE_OBJECT Arrays.fill(array, null); #endif size = 0; } @Override public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) { Objects.requireNonNull(action); for(int i = 0,m=size;i void forEach(E input, BI_OBJECT_CONSUMER KEY_VALUE_SPECIAL_GENERIC_TYPE action) { Objects.requireNonNull(action); for(int i = 0,m=size;i=0;i--) { if(COMPAREABLE_TO_KEY(array[i], value) < 0) value = array[index = i]; } } else { for(int i = index;i>=0;i--) { if(comparator.compare(array[i], value) < 0) value = array[index = i]; } } firstIndex = index; } return firstIndex; } private class Iter implements ITERATOR KEY_GENERIC_TYPE { @Override public boolean hasNext() { return !isEmpty(); } @Override public KEY_TYPE NEXT() { return dequeue(); } } }