package com.jwetherell.algorithms.data_structures; import java.util.Arrays; import com.jwetherell.algorithms.data_structures.interfaces.IStack; @SuppressWarnings("unchecked") public interface Stack extends IStack { /** * This stack implementation is backed by an array. * * @author Justin Wetherell */ public static class ArrayStack implements Stack { 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>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 toLifoQueue() { return (new JavaCompatibleArrayStack(this)); } /** * {@inheritDoc} */ @Override public java.util.Collection toCollection() { return (new JavaCompatibleArrayStack(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 */ public static class LinkedStack implements Stack { private Node top = null; private int size = 0; public LinkedStack() { top = null; size = 0; } /** * {@inheritDoc} */ @Override public boolean push(T value) { return push(new Node(value)); } /** * Push node onto the stack. * * @param node * to push on the stack. */ private boolean push(Node node) { if (top == null) { top = node; } else { Node oldTop = top; top = node; top.below = oldTop; oldTop.above = top; } size++; return true; } /** * {@inheritDoc} */ @Override public T pop() { if (top==null) return null; Node 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 current = top; for (int i=0; i node = top; while (node != null && (!node.value.equals(value))) { node = node.below; } if (node == null) return false; return remove(node); } private boolean remove(Node node) { Node above = node.above; Node 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 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 keys = new java.util.HashSet(); Node node = top; if (node!=null) { keys.add(node.value); if (node.above!=null) return false; Node child = node.below; while (child!=null) { if (!validate(child,keys)) return false; child = child.below; } } return (keys.size()==size()); } private boolean validate(Node node, java.util.Set keys) { if (node.value==null) return false; keys.add(node.value); Node child = node.below; if (child!=null && !child.above.equals(node)) return false; return true; } /** * {@inheritDoc} */ @Override public java.util.Queue toLifoQueue() { return (new JavaCompatibleLinkedStack(this)); } /** * {@inheritDoc} */ @Override public java.util.Collection toCollection() { return (new JavaCompatibleLinkedStack(this)); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder builder = new StringBuilder(); Node node = top; while (node != null) { builder.append(node.value).append(", "); node = node.below; } return builder.toString(); } private static class Node { private T value = null; private Node above = null; private Node 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 extends java.util.AbstractQueue { private ArrayStack stack = null; public JavaCompatibleArrayStack(ArrayStack 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 iterator() { return (new ArrayStackIterator(this.stack)); } private static class ArrayStackIterator implements java.util.Iterator { private ArrayStack stack = null; private int last = -1; private int index = 0; private ArrayStackIterator(ArrayStack 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 extends java.util.AbstractQueue { private LinkedStack stack = null; public JavaCompatibleLinkedStack(LinkedStack 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 iterator() { return (new LinkedStackIterator(stack)); } private static class LinkedStackIterator implements java.util.Iterator { private LinkedStack stack = null; private LinkedStack.Node lastNode = null; private LinkedStack.Node nextNode = null; private LinkedStackIterator(LinkedStack stack) { this.stack = stack; LinkedStack.Node 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 current = nextNode; if (current!=null) { lastNode = nextNode; nextNode = current.above; return current.value; } return null; } /** * {@inheritDoc} */ @Override public void remove() { stack.remove(lastNode); } } } }