You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

643 lines
15 KiB
Java

package com.jwetherell.algorithms.data_structures;
import java.util.Arrays;
import com.jwetherell.algorithms.data_structures.interfaces.IStack;
@SuppressWarnings("unchecked")
public interface Stack<T> extends IStack<T> {
/**
* This stack implementation is backed by an array.
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public static class ArrayStack<T> implements Stack<T> {
private static final int MINIMUM_SIZE = 1024;
private T[] array = (T[]) new Object[MINIMUM_SIZE];
private int size = 0;
/**
* {@inheritDoc}
*/
@Override
public boolean push(T value) {
if (size >= array.length)
grow();
array[size++] = value;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public T pop() {
if (size <= 0) return null;
T t = array[--size];
array[size] = null;
int shrinkSize = array.length>>1;
if (shrinkSize >= MINIMUM_SIZE && size < shrinkSize)
shrink();
return t;
}
/**
* {@inheritDoc}
*/
@Override
public T peek() {
if (size <= 0) return null;
T t = array[--size];
return t;
}
/**
* Get item at index.
*
* @param index of item.
* @return T at index.
*/
public T get(int index) {
if (index>=0 && index<size) return array[index];
return null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(T value) {
for (int i = 0; i < size; i++) {
T obj = array[i];
if (obj.equals(value)) {
return (remove(i));
}
}
return false;
}
private boolean remove(int index) {
if (index != --size) {
// Shift the array down one spot
System.arraycopy(array, index + 1, array, index, size - index);
}
array[size] = null;
int shrinkSize = array.length>>1;
if (shrinkSize >= MINIMUM_SIZE && size < shrinkSize)
shrink();
return true;
}
// Grow the array by 50%
private void grow() {
int growSize = size + (size<<1);
array = Arrays.copyOf(array, growSize);
}
// Shrink the array by 50%
private void shrink() {
int shrinkSize = array.length>>1;
array = Arrays.copyOf(array, shrinkSize);
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
size = 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(T value) {
for (int i = 0; i < size; i++) {
T obj = array[i];
if (obj.equals(value))
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate() {
int localSize = 0;
for (int i=0; i<array.length; i++) {
T t = array[i];
if (i<size) {
if (t==null) return false;
localSize++;
} else {
if (t!=null) return false;
}
}
return (localSize==size);
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Queue<T> toLifoQueue() {
return (new JavaCompatibleArrayStack<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Collection<T> toCollection() {
return (new JavaCompatibleArrayStack<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = size - 1; i >= 0; i--) {
builder.append(array[i]).append(", ");
}
return builder.toString();
}
}
/**
* This stack implementation is backed by a linked list.
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public static class LinkedStack<T> implements Stack<T> {
private Node<T> top = null;
private int size = 0;
public LinkedStack() {
top = null;
size = 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean push(T value) {
return push(new Node<T>(value));
}
/**
* Push node onto the stack.
*
* @param node
* to push on the stack.
*/
private boolean push(Node<T> node) {
if (top == null) {
top = node;
} else {
Node<T> oldTop = top;
top = node;
top.below = oldTop;
oldTop.above = top;
}
size++;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public T pop() {
if (top==null) return null;
Node<T> nodeToRemove = top;
top = nodeToRemove.below;
if (top != null) top.above = null;
T value = nodeToRemove.value;
size--;
return value;
}
/**
* {@inheritDoc}
*/
@Override
public T peek() {
return (top!=null)?top.value:null;
}
/**
* Get item at index.
*
* @param index of item.
* @return T at index.
*/
public T get(int index) {
Node<T> current = top;
for (int i=0; i<index; i++) {
if (current==null) break;
current = current.below;
}
return (current!=null)?current.value:null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(T value) {
// Find the node
Node<T> node = top;
while (node != null && (!node.value.equals(value))) {
node = node.below;
}
if (node == null) return false;
return remove(node);
}
private boolean remove(Node<T> node) {
Node<T> above = node.above;
Node<T> below = node.below;
if (above != null && below != null) {
above.below = below;
below.above = above;
} else if (above != null && below == null) {
above.below = null;
} else if (above == null && below != null) {
// Node is the top
below.above = null;
top = below;
} else {
// prev==null && next==null
top = null;
}
size--;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
top = null;
size = 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(T value) {
if (top == null) return false;
Node<T> node = top;
while (node != null) {
if (node.value.equals(value)) return true;
node = node.below;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate() {
java.util.Set<T> keys = new java.util.HashSet<T>();
Node<T> node = top;
if (node!=null) {
keys.add(node.value);
if (node.above!=null) return false;
Node<T> child = node.below;
while (child!=null) {
if (!validate(child,keys)) return false;
child = child.below;
}
}
return (keys.size()==size());
}
private boolean validate(Node<T> node, java.util.Set<T> keys) {
if (node.value==null) return false;
keys.add(node.value);
Node<T> child = node.below;
if (child!=null && !child.above.equals(node)) return false;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Queue<T> toLifoQueue() {
return (new JavaCompatibleLinkedStack<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Collection<T> toCollection() {
return (new JavaCompatibleLinkedStack<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Node<T> node = top;
while (node != null) {
builder.append(node.value).append(", ");
node = node.below;
}
return builder.toString();
}
private static class Node<T> {
private T value = null;
private Node<T> above = null;
private Node<T> below = null;
private Node(T value) {
this.value = value;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "value=" + value + " above=" + ((above != null) ? above.value : "NULL") + " below="
+ ((below != null) ? below.value : "NULL");
}
}
}
public static class JavaCompatibleArrayStack<T> extends java.util.AbstractQueue<T> {
private ArrayStack<T> stack = null;
public JavaCompatibleArrayStack(ArrayStack<T> stack) {
this.stack = stack;
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return stack.push(value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(Object value) {
return stack.remove((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(Object value) {
return stack.contains((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean offer(T value) {
return stack.push(value);
}
/**
* {@inheritDoc}
*/
@Override
public T peek() {
return stack.peek();
}
/**
* {@inheritDoc}
*/
@Override
public T poll() {
return stack.pop();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return stack.size();
}
/**
* {@inheritDoc}
*
* This iterator is NOT thread safe and is invalid when the data structure is modified.
*/
@Override
public java.util.Iterator<T> iterator() {
return (new ArrayStackIterator<T>(this.stack));
}
private static class ArrayStackIterator<T> implements java.util.Iterator<T> {
private ArrayStack<T> stack = null;
private int last = -1;
private int index = 0;
private ArrayStackIterator(ArrayStack<T> stack) {
this.stack = stack;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return (index+1<=stack.size);
}
/**
* {@inheritDoc}
*/
@Override
public T next() {
if (index>=stack.size) return null;
last = index;
return stack.array[index++];
}
/**
* {@inheritDoc}
*/
@Override
public void remove() {
stack.remove(last);
}
}
}
public static class JavaCompatibleLinkedStack<T> extends java.util.AbstractQueue<T> {
private LinkedStack<T> stack = null;
public JavaCompatibleLinkedStack(LinkedStack<T> stack) {
this.stack = stack;
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return stack.push(value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(Object value) {
return stack.remove((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(Object value) {
return stack.contains((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean offer(T value) {
return stack.push(value);
}
/**
* {@inheritDoc}
*/
@Override
public T peek() {
return stack.peek();
}
/**
* {@inheritDoc}
*/
@Override
public T poll() {
return stack.pop();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return stack.size();
}
/**
* {@inheritDoc}
*
* This iterator is NOT thread safe and is invalid when the data structure is modified.
*/
@Override
public java.util.Iterator<T> iterator() {
return (new LinkedStackIterator<T>(stack));
}
private static class LinkedStackIterator<T> implements java.util.Iterator<T> {
private LinkedStack<T> stack = null;
private LinkedStack.Node<T> lastNode = null;
private LinkedStack.Node<T> nextNode = null;
private LinkedStackIterator(LinkedStack<T> stack) {
this.stack = stack;
LinkedStack.Node<T> current = stack.top;
while (current!=null && current.below!=null) current = current.below;
this.nextNode = current;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return (nextNode!=null);
}
/**
* {@inheritDoc}
*/
@Override
public T next() {
LinkedStack.Node<T> current = nextNode;
if (current!=null) {
lastNode = nextNode;
nextNode = current.above;
return current.value;
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void remove() {
stack.remove(lastNode);
}
}
}
}