X * Y + Z * W -> X Y * Z W * +
Notice all operands appear in same order as started - only operations move. Commands to transform above expression (working on it from left to right):
OUTPUT X PUSH * OUTPUT Y POP and OUTPUT operator PUSH + OUTPUT Z PUSH * OUTPUT W POP and OUTPUT operator POP and OUTPUT operator(Other rules - "(" is always pushed onto stack, ")" causes operators to be popped and output until pop off topmost "(" on stack. )
Big question: When do you push one operator on top of another and when do you pop off topmost operator before pushing on new one?
Answer given in terms of precedence of operators!
Programs which use stacks can often be rewritten to simply use recursion (since recursion deals with an implicit stack. Hence the maze-running program can be rewritten as follows, where caller is responsible for setting success to false and current to start originally:
public void runMaze() { Position origCurrent = current; // Save orig value current.visit(); success = current.equals(finish); // Are we finished? while (current != null && !success) { // Search until success or run out of cells current = nextUnvisited(); // Find new cell to visit if (current != null) { current.visit(); runMaze(); // Try solving maze from new current current = origCurrent; // reset to try again } } }
See on-line StackArray implementation:
public class StackArray implements Stack { protected int top; protected Object data[]; ...
The array implementation keeps the bottom of the stack at the beginning of the array. It grows toward the end of the array.
The only problem is if you attempt to push an element when the array is full. If so
Assert.pre(!isFull(),"Stack is not full.");will fail, raising an exception. Thus makes more sense to implement with Vector (see StackVector) to allow unbounded growth (at cost of occasional O(n) delays).
All operations are O(1) with exception of occasional push and clear, which should replace all entries by null in order to let them be garbage-collected.
See on-line StackList implementation.
Operations: peek, pop, isEmpty all O(1) for Array, Vector, and Linked List implementations. push can be O(n) in worst case for Vector, though average is O(1), other implementations always O(1). clear O(1) for linked list, O(n) for array or vector representation.
Arrays use a fixed amount of space: this wastes space if you reserve too much, while the program won't run if there is too little.
Vector provides more flexibility, but at the cost of occasional significant delays (though average cost of push is O(1))
The linked list implementation has all operations O(1) in worst case, but needs extra space for the links.