The Stack
The first example of a stack ADT is based on an array.
public class ArrayStack<T> {
// Java would use boxed types (Integer, String, Character)
// approach by storing items in an array, where the top item/node is updated
// after each method
private final int stackSize;
private final T[] stackArray;
private int topIndex;
public ArrayStack(int stackSize){
//care needed to keep this execution away from client code until T is known
this.stackSize = stackSize;
this.stackArray = (T[]) new Object[this.stackSize];
this.topIndex = -1;
}
/**
* Pushes a new element or node (the data of which can be null) to the top of the stack.
* New nodes' data can be null hence pop() and peek() return null if the data is null
* and throw exceptions when the given stack is empty. ArrayStack is static-array based
* hence push() returns -1 of the array is full and 1 if push was accomplished.
* */
public int push(T data) {
// check if stack is already full (unlike linked lists)
if (this.topIndex == this.stackSize - 1){
System.out.println("Stack is full, cannot push to stack");
return -1;
}
this.stackArray[++this.topIndex] = data;
return 1;
}
/**
* Removes and returns the uppermost node's or element's data from the stack; throws an
* EmptyStackException if stack is empty.
* */
public T pop(){
if (topIndex == -1){
System.out.println("Stack is empty");
throw new EmptyStackException();
}
return stackArray[topIndex--];
}
/**
* Returns a copy of the uppermost node (which can be null) or element of the given stack.
* Throws an EmptyStackException if stack is empty.
* */
public T peek(){
if (topIndex == -1){
System.out.println("Stack is already empty");
throw new EmptyStackException();
}
return stackArray[topIndex];
}
/**
* Returns true if the stack is empty and false if not
* */
public boolean isEmpty(){
return topIndex < 0;
}
}
The next example is based on the custom Linked List.
public class ListStack<T> {
// when instantiating a Stack, the respective nodes are private and
// accessible/viewed via pop(), push(), peek() and isEmpty()
// note that the Stack and Queue are implemented here as linked lists
// to allow for dynamic allocation (arrays may also be employed; see ArrayStack)
private static class StackNode<T> {
private T data;
private StackNode<T> next;
public StackNode(T data){
this.data = data;
}
}
// references the top of the stack (last node in, first node out)
private StackNode<T> top;
/**
* Removes and returns the uppermost node's or element's data from the stack;
* throws an EmptyStackException if stack is empty.
* */
public T pop(){
if (top == null){
throw new EmptyStackException();
}
T item = top.data;
top = top.next;
return item;
}
/**
* Pushes a new element or node (the data of which can be null) to the top
* of the stack. New nodes' data can be null hence pop() and peek() return
* null if the data is null and throw exceptions when
* the given stack is empty.
* */
public void push(T item){
StackNode<T> newItem = new StackNode<>(item);
newItem.next = top;
top = newItem;
}
/**
* Returns a copy of the uppermost node (which can be null) or element of the stack.
* Throws an EmptyStackException if stack is empty.
* */
public T peek(){
if (top == null){
throw new EmptyStackException();
}
return top.data;
}
/**
* Returns true if the stack is empty and false if not
* */
public boolean isEmpty(){
return this.top == null;
}
}