package sort;
/** A growable class for storing ints. */
public class IntVector implements Cloneable {
// The underlying storage for this.
private int[] elems;
// The number of elements in this.
private int size;
/** Creates an IntVector with the given initial
* capacity.
* @param capacity the initial capacity of this
*/
public IntVector(int capacity) {
this.elems = new int[capacity];
this.size = 0;
}
/** Creates an IntVector with the given array and size.
*
WARNING: This does not copy the given array but uses it
* directly, so the internal data is left unprotected. Use carefully.
* @param nums the array to use as the underlying array of
* this
* @param size the initial size (not capacity) of this
*/
protected IntVector(int[] nums, int size) {
this.elems = nums;
this.size = size;
}
/** Creates an IntVector with the default capacity
* (10).
*/
public IntVector() {
this(10);
}
/** Adds the given element to the end of this.
* @param the element to insert into this
*/
public void addElement(int x) {
if (size >= elems.length) {
doubleCapacity();
addElement(x);
} else {
elems[size++] = x;
}
}
/** Returns the number of elements contained in this.
* @return the number of elements in this
*/
public int size() {
return size;
}
/** Adds elements from the given array to the end of
* this, in order.
* @param nums the array from which to insert elements
* @param offset the position from which to start inserting
* @param length the number of elements to insert
*/
public void addAll(int[] nums, int offset, int length) {
while (elems.length - size < length) {
doubleCapacity();
}
System.arraycopy(nums, offset, elems, size, length);
size += length;
}
// Doubles the capacity of this (linear operation)
private void doubleCapacity() {
int[] tmp = new int[elems.length * 2 + 1];
System.arraycopy(elems, 0, tmp, 0, elems.length);
elems = tmp;
}
/** Adds all elements in the given IntVector to
* this.
* @param iv the IntVector from which to insert elements
*/
public void concat(IntVector iv) {
if (size + iv.size > elems.length) {
int[] tmp = new int[2 * (size + iv.size) + 1];
System.arraycopy(elems, 0, tmp, 0, size);
System.arraycopy(iv.elems, 0, tmp, size, iv.size);
elems = tmp;
} else {
System.arraycopy(iv.elems, 0, elems, size, iv.size);
}
size += iv.size;
}
/** Clears this of any elements. */
public void clear() {
size = 0;
}
/** Copies as many elements as can fit from this into
* the target array.
* @param target the array to copy elements into
* @param offset the position in the destination at which to start
* copying
* @return the number of elements copied
*/
public int copyElements(int[] target, int offset) {
int num = Math.min(size, target.length - offset);
System.arraycopy(elems, 0, target, offset, num);
return num;
}
/** Creates a deep copy of this.
* @return a deep copy of this
*/
public Object clone() {
IntVector iv = new IntVector(elems.length);
System.arraycopy(elems, 0, iv.elems, 0, size);
iv.size = size;
return iv;
}
/** Tests if this is equal to the given
* Object.
* @param obj the Object to compare this
* to
* @return whether or not this is equal to the argument
*/
public boolean equals(Object obj) {
if (obj instanceof IntVector) {
IntVector iv = (IntVector) obj;
return iv.size() == size() &&
Util.compare(iv.elems, 0, elems, 0, size());
} else {
return false;
}
}
/** Prints the elements in this to the given
* PrintStream, one per line.
* @param ps the target PrintStream
*/
protected void print(java.io.PrintStream ps) {
ps.println("------ IntVector: " + size + " elements ------");
for (int i = 0; i < size; i++) {
ps.println(elems[i]);
}
ps.println("------------------------");
}
/** Tests this class. */
protected static boolean test() {
System.out.println("Testing IntVector...");
boolean res = insertTest();
res &= concatTest();
res &= cloneTest();
res &= copyTest();
if (res) {
System.out.println("IntVector tests passed.");
} else {
System.out.println("IntVector tests failed!");
}
return res;
}
// Tests the insertion methods of this class.
private static boolean insertTest() {
System.out.println("=> running insert tests...");
int[] nums = new int[1000];
int[] nums2 = new int[nums.length];
int off, len;
IntVector iv = new IntVector();
for (int i = 0; i < nums.length; i++) {
nums[i] = Util.random();
nums2[i] = Util.random();
iv.addElement(nums[i]);
}
if (iv.size() != nums.length ||
!Util.compare(nums, 0, iv.elems, 0, nums.length)) {
}
iv.clear();
if (iv.size() != 0) {
return fail("insert tests (#1)");
}
iv.addAll(nums2, 0, nums2.length);
if (iv.size() != nums2.length ||
!Util.compare(nums2, 0, iv.elems, 0, nums2.length)) {
return fail("insert tests (#2)");
}
iv.clear();
off = 24;
len = nums.length - off - nums.length / 3;
iv.addAll(nums, off, len);
if (iv.size() != len ||
!Util.compare(nums, off, iv.elems, 0, len)) {
return fail("insert tests (#3)");
}
System.out.println("=> insert tests passed.");
return true;
}
// Tests the concatenation method of this class.
private static boolean concatTest() {
System.out.println("=> running concat tests...");
int[] nums = new int[1000];
int off2 = nums.length / 2;
int len2 = nums.length - nums.length / 2;
IntVector iv, iv2;
for (int i = 0; i < nums.length; i++) {
nums[i] = Util.random();
}
iv = new IntVector();
iv.addAll(nums, 0, off2);
iv2 = new IntVector();
iv2.addAll(nums, off2, len2);
iv.concat(iv2);
if (iv2.size() != len2 || iv.size() != nums.length ||
!Util.compare(nums, 0, iv.elems, 0, nums.length)) {
return fail("concat tests (#1)");
}
iv = new IntVector();
iv.addAll(nums, 0, off2);
iv2 = new IntVector();
iv2.addAll(nums, off2, len2);
iv2.concat(iv);
if (iv.size() != off2 || iv2.size() != nums.length ||
!Util.compare(nums, off2, iv2.elems, 0, len2) ||
!Util.compare(nums, 0, iv2.elems, len2, off2)) {
return fail("concat tests (#2)");
}
System.out.println("=> concat tests passed.");
return true;
}
// Tests the clone method of this class.
private static boolean cloneTest() {
System.out.println("=> running clone tests...");
IntVector iv = new IntVector(), iv2;
int num = 1000;
for (int i = 0; i < num; i++) {
iv.addElement(Util.random());
}
iv2 = (IntVector) iv.clone();
if (iv == iv2 || iv.elems == iv2.elems || !iv.equals(iv2)) {
return fail("clone tests (#1)");
}
System.out.println("=> clone tests passed.");
return true;
}
// Tests the element copy method of this class.
private static boolean copyTest() {
System.out.println("=> running copy tests...");
int num = 1000, x;
int[] nums;
IntVector iv = new IntVector();
for (int i = 0; i < num; i++) {
iv.addElement(Util.random());
}
nums = new int[iv.size()];
x = iv.copyElements(nums, 0);
if (x != iv.size() ||
!Util.compare(nums, 0, iv.elems, 0, iv.size())) {
return fail("copy tests (#1)");
}
x = iv.copyElements(nums, nums.length - 100);
if (x != 100 ||
!Util.compare(iv.elems, 0, nums, nums.length - 100,
100)) {
return fail("copy tests (#2)");
}
nums = new int[100];
x = iv.copyElements(nums, 0);
if (x != 100 ||
!Util.compare(nums, 0, iv.elems, 0, 100)) {
return fail("copy tests (#3)");
}
x = iv.copyElements(nums, nums.length - 50);
if (x != 50 ||
!Util.compare(iv.elems, 0, nums, nums.length - 50,
50)) {
return fail("copy tests (#4)");
}
nums = new int[2 * iv.size()];
x = iv.copyElements(nums, 0);
if (x != iv.size() ||
!Util.compare(nums, 0, iv.elems, 0, iv.size())) {
return fail("copy tests (#5)");
}
x = iv.copyElements(nums, nums.length - 100);
if (x != 100 ||
!Util.compare(iv.elems, 0, nums, nums.length - 100,
100)) {
return fail("copy tests (#6)");
}
System.out.println("=> copy tests passed.");
return true;
}
// Prints out an error message and returns false.
private static boolean fail(String msg) {
System.out.println("Error in IntVector: " + msg + " failed.");
return false;
}
}