/**
* com.mckoi.util.IntegerVector 10 Mar 1998
*
* Mckoi SQL Database ( http://www.mckoi.com/database )
* Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License Version 2 for more details.
*
* You should have received a copy of the GNU General Public License
* Version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Change Log:
*
*
*/
package com.mckoi.util;
/**
* Similar to the Vector class, except this can only store integer values.
* <p>
* @author Tobias Downer
*/
public final class IntegerVector implements java.io.Serializable {
/**
* The int array.
*/
protected int[] list;
/**
* The index of the last value of the array.
*/
protected int index;
/**
* The Constructors.
*/
public IntegerVector() {
this(32);
}
public IntegerVector(int initial_list_size) {
index = 0;
list = new int[initial_list_size];
}
public IntegerVector(IntegerVector vec) {
if (vec != null && vec.list != null) {
list = new int[vec.list.length];
index = vec.index;
System.arraycopy(vec.list, 0, list, 0, index);
}
else {
index = 0;
list = new int[0];
}
}
public IntegerVector(IntegerListInterface i_list) {
this(i_list.size());
if (i_list instanceof AbstractBlockIntegerList) {
AbstractBlockIntegerList bilist = (AbstractBlockIntegerList) i_list;
int bill_size = bilist.size();
bilist.copyToArray(list, 0, bill_size);
index = bill_size;
}
else {
IntegerIterator i = i_list.iterator();
// NOTE: We are guarenteed the size of the 'list' array matches the size
// of input list.
while (i.hasNext()) {
list[index] = i.next();
++index;
}
}
}
/**
* Ensures there's enough room to make a single addition to the list.
*/
private void ensureCapacityForAddition() {
if (index >= list.length) {
int[] old_arr = list;
int grow_size = old_arr.length + 1;
// Put a cap on the new size.
if (grow_size > 35000) {
grow_size = 35000;
}
int new_size = old_arr.length + grow_size;
list = new int[new_size];
System.arraycopy(old_arr, 0, list, 0, index);
}
}
/**
* Ensures there's enough room to make 'n' additions to the list.
*/
private void ensureCapacityForAdditions(int n) {
int intended_size = index + n;
if (intended_size > list.length) {
int[] old_arr = list;
int grow_size = old_arr.length + 1;
// Put a cap on the new size.
if (grow_size > 35000) {
grow_size = 35000;
}
int new_size = Math.max(old_arr.length + grow_size, intended_size);
list = new int[new_size];
System.arraycopy(old_arr, 0, list, 0, index);
}
}
/**
* Adds an int to the vector.
*/
public void addInt(int val) {
// if (list == null) {
// list = new int[64];
// }
ensureCapacityForAddition();
list[index] = val;
++index;
}
/**
* Removes an Int from the specified position in the list.
*/
public void removeIntAt(int pos) {
--index;
System.arraycopy(list, pos + 1, list, pos, (index - pos));
}
/**
* Removes the first Int found that matched the specified value.
*/
public void removeInt(int val) {
int pos = indexOf(val);
if (pos == -1) {
throw new RuntimeException("Tried to remove none existant int.");
}
removeIntAt(pos);
}
/**
* Crops the IntegerVector so it only contains values between start
* (inclusive) and end (exclusive). So;
* crop({ 4, 5, 4, 3, 9, 7 }, 0, 3)
* would return {4, 5, 4)
* and,
* crop({ 4, 5, 4, 3, 9, 7 }, 3, 4)
* would return {3}
*/
public void crop(int start, int end) {
if (start < 0) {
throw new Error("Crop start < 0.");
}
else if (start == 0) {
if (end > index) {
throw new Error("Crop end was past end.");
}
index = end;
}
else {
if (start >= index) {
throw new Error("start >= index");
}
int length = (end - start);
if (length < 0) {
throw new Error("end - start < 0");
}
System.arraycopy(list, start, list, 0, length);
index = length;
}
}
/**
* Inserts an int at the given position.
*/
public void insertIntAt(int val, int pos) {
if (pos >= index) {
throw new ArrayIndexOutOfBoundsException(pos + " >= " + index);
}
// if (list == null) {
// list = new int[64];
// }
ensureCapacityForAddition();
System.arraycopy(list, pos, list, pos + 1, (index - pos));
++index;
list[pos] = val;
}
/**
* Sets an int at the given position, overwriting anything that was
* previously there. It returns the value that was previously at the element.
*/
public int setIntAt(int val, int pos) {
if (pos >= index) {
throw new ArrayIndexOutOfBoundsException(pos + " >= " + index);
}
int old = list[pos];
list[pos] = val;
return old;
}
/**
* Places an int at the given position, overwriting anything that was
* previously there. It returns the value that was previously at the
* element. If 'pos' points to a place outside the bounds of the list then
* the list is expanded to include this value.
*/
public int placeIntAt(int val, int pos) {
int llength = list.length;
if (pos >= list.length) {
ensureCapacityForAdditions((llength - index) + (pos - llength) + 5);
}
if (pos >= index) {
index = pos + 1;
}
int old = list[pos];
list[pos] = val;
return old;
}
/**
* Appends an IntegerVector to the end of the array. Returns this object.
*/
public IntegerVector append(IntegerVector vec) {
if (vec != null) {
int size = vec.size();
// Make sure there's enough room for the new array
ensureCapacityForAdditions(size);
// Copy the list into this vector.
System.arraycopy(vec.list, 0, list, index, size);
index += size;
// int size = vec.size();
// for (int i = 0; i < size; ++i) {
// addInt(vec.intAt(i));
// }
}
return this;
}
/**
* Returns the Int at the given position.
*/
public int intAt(int pos) {
if (pos >= index) {
throw new ArrayIndexOutOfBoundsException(pos + " >= " + index);
}
return list[pos];
}
/**
* Returns the first index of the given row in the array, or -1 if not
* found.
*/
public int indexOf(int val) {
for (int i = 0; i < index; ++i) {
if (list[i] == val) {
return i;
}
}
return -1;
}
/**
* Returns true if the vector contains the given value.
*/
public boolean contains(int val) {
return (indexOf(val) != -1);
}
/**
* Returns the size of the vector.
*/
public int getSize() {
return index;
}
/**
* Returns the size of the vector.
*/
public int size() {
return index;
}
/**
* Converts the vector into an int[] array.
*/
public int[] toIntArray() {
if (getSize() != 0) {
int[] out_list = new int[getSize()];
System.arraycopy(list, 0, out_list, 0, getSize());
return out_list;
}
return null;
}
/**
* Clears the object to be re-used.
*/
public void clear() {
index = 0;
}
/**
* Converts the vector into a String.
*/
public String toString() {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < index; ++i) {
buf.append(list[i]);
buf.append(", ");
}
return new String(buf);
}
/**
* Returns true if this vector is equal to the given vector.
*/
public boolean equals(IntegerVector ivec) {
int dest_index = ivec.index;
if (index != dest_index) {
return false;
}
for (int i = 0; i < index; ++i) {
if (list[i] != ivec.list[i]) {
return false;
}
}
return true;
}
/**
* Reverses all the list of integers. So integer[0] is swapped with
* integer[n - 1], integer[1] is swapped with integer[n - 2], etc where
* n is the size of the vector.
*/
public void reverse() {
final int upper = index - 1;
final int bounds = index / 2;
int end_index, temp;
// Swap ends and interate the two end pointers inwards.
// i = lower end
// upper - i = upper end
for (int i = 0; i < bounds; ++i) {
end_index = upper - i;
temp = list[i];
list[i] = list[end_index];
list[end_index] = temp;
}
}
/**
* These methods are algorithms that can be used on the array, such as
* sorting and searching.
*/
/**
* Performs a quick sort on the array between the min and max bounds.
*/
public final void quickSort(int min, int max) {
int left = min;
int right = max;
if (max > min) {
int mid = list[(min + max) / 2];
while (left < right) {
while (left < max && list[left] < mid) {
++left;
}
while (right > min && list[right] > mid) {
--right;
}
if (left <= right) {
if (left != right) {
int t = list[left];
list[left] = list[right];
list[right] = t;
}
++left;
--right;
}
}
if (min < right) {
quickSort(min, right);
}
if (left < max) {
quickSort(left, max);
}
}
}
/**
* Performs a quick sort on the entire vector.
*/
public final void quickSort() {
quickSort(0, index - 1);
}
/**
* This is a very quick search for a value given a sorted array. The search
* is performed between the lower and higher bounds of the array. If the
* requested value is not found, it returns the index where the value should
* be 'inserted' to maintain a sorted list.
*/
public final int sortedIndexOf(int val, int lower, int higher) {
if (lower >= higher) {
if (lower < index && val > list[lower]) {
return lower + 1;
}
else {
return lower;
}
}
int mid = (lower + higher) / 2;
int mid_val = list[mid];
if (val == mid_val) {
return mid;
}
else if (val < mid_val) {
return sortedIndexOf(val, lower, mid - 1);
}
else {
return sortedIndexOf(val, mid + 1, higher);
}
}
/**
* Searches the entire sorted list for the given value and returns the index
* of it. If the value is not found, it returns the place in the list where
* the value should be insorted to maintain a sorted list.
*/
public final int sortedIndexOf(int val) {
return sortedIndexOf(val, 0, index - 1);
}
/**
* Given a sorted list, this will return the count of this value in the
* list. This uses a quick search algorithm so should be quite fast.
*/
public final int sortedIntCount(int val) {
if (index == 0) {
return 0;
}
int count = 0;
int size = index - 1;
int i = sortedIndexOf(val, 0, size);
if (i > size) {
return 0;
}
int temp_i = i;
while (temp_i >= 0 && list[temp_i] == val) {
++count;
--temp_i;
}
temp_i = i + 1;
while (temp_i <= size && list[temp_i] == val) {
++count;
++temp_i;
}
return count;
}
/**
* Test routine to check vector is sorted.
*/
public boolean isSorted() {
int cur = Integer.MIN_VALUE; //-1000000;
for (int i = 0; i < index; ++i) {
int a = list[i];
if (a >= cur) {
cur = a;
}
else {
return false;
}
}
return true;
}
}
|