next up previous index
Next: Interfaces Up: Stacks Previous: Stacks   Index

Simple Implementation

Figure 2.1 shows a simple implementation of the idea.

Figure 2.1: A simple implementation of the stack.
public class SimpleStack {

    private Object[] stack;
    private int top; // for storing next item
  
    public SimpleStack(int capacity) {
        stack = new Object[capacity];
        top = 0; 
    }

    public boolean isEmpty() {
        return top == 0;
    }

    public boolean isFull() {
        return top == stack.length;
    }

    public void push(Object item) throws Exception {
        if (isFull()) {
            throw new Exception("stack overflow");
        } else {
            stack[top++] = item;
        }
    }

    public Object pop() throws Exception {
        if (isEmpty()) {
            throw new Exception("stack underflow");
        } else {
            return stack[--top];
        }
    }
}

The stack is represented by a private array of objects
private Object[] stack;
which means that anything can be placed on the stack, provided it is represented as an Object. There is also a private pointer to the top of the stack
private int top;
This will represent the index in the array at which the next object pushed onto the stack is to be stored. This increases by one when another object is pushed onto the stack, and decreases by one when an object is popped.

There is a single constructor

public SimpleStack(int capacity) {
    stack = new Object[capacity];
    top = 0; 
}
which requires the user to specify the maximum capacity of the stack. For example, an application might declare a stack using
SimpleStack s = new SimpleStack(20);
The constructor then assigns a new array of 20 objects to the instance variable stack and sets the top pointer to zero.

There are two public methods for monitoring the status of the stack:

public boolean isEmpty() {
    return top == 0;
}
public boolean isFull() {
    return top == stack.length;
}
The stack is empty when the top pointer is zero, and it is full if the top pointer is equal to the size of the stack array. This is because top now lies beyond the bounds of the array.

Pushing an object onto the stack is simple.

public void push(Object item) throws Exception {
    if (isFull()) {
        throw new Exception("stack overflow");
    } else {
        stack[top++] = item;
    }
}
If the stack is full, we must raise an exception. Otherwise the item is stored in stack[top] and top is incremented by 1, ready for storing the next push. The last line is equivalent to
stack[top] = item;
top = top+1;

Popping an item from the stack is similar, except that we must now raise an exception if the stack is empty.

public Object pop() throws Exception {
    if (isEmpty()) {
        throw new Exception("stack underflow");
    } else {
        return stack[--top];
    }
}
Notice that we must now decrease top by 1 before accessing the top of the stack. This is because of our convention that top points to the next free place in the stack, where a push will be written. The last item pushed onto the stack is therefore at top-1. We have to decrease top by 1 when we pop from the stack in any case. Our convention means that we do it first. The last line is equivalent to
top = top-1;
return stack[top];
A brief discussion of the use of exceptions in the DataStructures package is provided below.


next up previous index
Next: Interfaces Up: Stacks Previous: Stacks   Index
Peter Williams 2005-06-07