/*
* Nathaniel Lim
* Williams College: CSCI 136
* 3/3/08
* Lab 3: Dynamic Array
*/
import java.util.Comparator;
public class Array<Value> {
private Value[] data;
private int count;
public Array(){
data = allocateArray(0);
count = 0;
}
public static void main (String [] args){
}
//For debugging
public static void printArray(Object[] x){
for (int i = 0; i < x.length; i++){
System.out.print (x[i] + ", ");
}
}
//Ignore the issues that Java takes with this cast
@SuppressWarnings("unchecked")
private Value[] allocateArray(int n){
return (Value[])(new Object[n]);
}
/**
* setSize sets count = n and
* increases the data size if needed by doubling the data array
* decreases the data if n is smaller than half the data array
* truncates the data if n < count
* by setting the remaining elements to null
* if n > count, but n < data.length, no adjustments are done to
* data (this case should happen a majority of the time.
*/
public void setSize(int n){
assert n >= 0;
assert data!=null;
if (data.length == 0){
data = allocateArray(n);
} else {
if (n > data.length){
Value[] output = allocateArray(2*data.length);
System.arraycopy(data, 0, output, 0, count);
data = output;
} else if ( n < data.length/2){
Value[] output = allocateArray(data.length/2);
System.arraycopy(data, 0, output, 0, n);
data=output;
} else if (n < count){
for (int i = n; i < count; i++){
data[i] = null;
}
}
}
count = n;
}
//User should not be aware of data.length
public int size(){
return count;
}
//make the ith element equal to v
public void set(int i, Value v){
assert (i >= 0) && (i<count);
data[i] = v;
}
public String toString(){
String out = "{";
for (int i = 0; i < count; i++) {
out += data[i] + ", ";
}
out+="}";
return out;
}
public Value get(int i){
assert (i > 0) && (i < count);
return data[i];
}
//Add to the end
public void add (Value v){
setSize(count +1);
set (count-1, v);
}
// "insert" v into data at 'i' by first moving all the elements
// to the right, making room to set data[i] to v
public void add (int i, Value v){
assert i > 0 && i < count;
setSize(count+1);
System.arraycopy(data, i, data, i+1, count-i);
data[i] = v;
}
public void clear(){
data = allocateArray(0);
count = 0;
}
public boolean isEmpty() {
return count == 0 && data.length == 0;
}
public Value[] toArray(){
Value[] out = allocateArray(count);
System.arraycopy(data, 0, out, 0, count);
return out;
}
public Value remove(int i){
assert i >= 0 && i < count;
//Remove by getting the value at i, and then shifting
//all the elements to the right of i one to the left.
Value out = get(i);
System.arraycopy(data, i+1, data, i, count-i);
return out;
}
public void trimToSize(){
Value[] out = allocateArray(count);
System.arraycopy(data, 0, out, 0, count);
data = out;
}
public void sort(Comparator<Value> comparator) {
trimToSize();
mergeSort(data, comparator);
}
//Recursive implementation of mergeSort, done in place.
private void mergeSort(Value[] c, Comparator<Value> comparator) {
assert c != null;
//Do nothing if the size of the array is 1 or less.
if (c.length > 1) {
Value[] a = allocateArray(c.length / 2);
Value[] b = allocateArray(c.length - a.length);
System.arraycopy(c, 0, a, 0, a.length);
System.arraycopy(c, a.length, b, 0, b.length);
mergeSort(a, comparator);
mergeSort(b, comparator);
merge(a, b, c, comparator);
}
}
private void merge(Value[] a, Value[] b, Value[] c, Comparator<Value> comparator) {
assert a!=null && b!=null && c!=null;
assert a.length + b.length == c.length;
int i = 0;
int j = 0;
int k;
for (k = 0;(i < a.length) && (j < b.length); k++) {
if (comparator.compare(a[i], b[j]) < 0) {
c[k] = a[i];
i++;
} else {
c[k] = b[j];
j++;
}
}
if (i < a.length) {
System.arraycopy(a, i, c, k, a.length - i);
} else{
System.arraycopy(b, j, c, k, b.length - j);
}
}
}