ExpandableArrayStack.java
import java.util.NoSuchElementException;
/**
* An implementation of a stack using a "expandable" array, i.e., whenever the
* array would overflow, a new larger array is allocated and the elements are
* copied into the new array. A new smaller array is used whenever the queue
* gets too sparse as well.
*/
public class ExpandableArrayStack implements Stack {
private static final int MINIMUM_CAPACITY = 16;
private Object[] elements = new Object[MINIMUM_CAPACITY];
private int size = 0;
public void push(Object item) {
if (size == elements.length) {
reallocate(elements.length * 2);
}
elements[size++] = item;
}
public Object pop() {
var item = peek();
if (size <= capacity() / 4 && capacity() > MINIMUM_CAPACITY) {
reallocate(elements.length / 2);
}
elements[--size] = null;
return item;
}
public Object peek() {
if (isEmpty()) {
throw new NoSuchElementException();
}
return elements[size - 1];
}
@Override
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public int capacity() {
return elements.length;
}
private void reallocate(int newSize) {
Object[] newArray = new Object[newSize];
System.arraycopy(elements, 0, newArray, 0, size);
elements = newArray;
}
}
ExpandableArrayQueue.java
import java.util.NoSuchElementException;
/**
* An implementation of a queue using a "expandable" array, i.e., whenever the
* array would overflow, a new larger array is allocated and the elements are
* copied into the new array. A new smaller array is used whenever the queue
* gets too sparse as well.
*/
public class ExpandableArrayQueue implements Queue {
private static final int MINIMUM_CAPACITY = 16;
private Object[] elements = new Object[MINIMUM_CAPACITY];
private int size = 0;
private int head = 0; // index of the current front item, if one exists
private int tail = 0; // index of next item to be added
public void enqueue(Object item) {
if (size == elements.length) {
reallocate(elements.length * 2);
}
elements[tail] = item;
tail = (tail + 1) % elements.length;
size++;
}
public Object dequeue() {
var item = peek();
if (size <= capacity() / 4 && capacity() > MINIMUM_CAPACITY) {
reallocate(elements.length / 2);
}
elements[head] = null;
head = (head + 1) % elements.length;
size--;
return item;
}
public Object peek() {
if (isEmpty()) {
throw new NoSuchElementException();
}
return elements[head];
}
@Override
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public int capacity() {
return elements.length;
}
/*
* When reallocating, always make the new head 0.
*/
private void reallocate(int newSize) {
Object[] newArray = new Object[newSize];
for (var i = 0; i < size(); i++) {
newArray[i] = elements[(head + i) % capacity()];
}
head = 0;
tail = size();
elements = newArray;
}
}