6 Stack ADTs • Stack concepts. • Stack applications. • A stack ADT: requirements, contract. • Implementations of stacks: using arrays, linked lists. • Stacks in the Java class library. © 2001, D.A. Watt and D.F. Brown 6-1 Stack concepts (1) • A stack is a last-in-first-out sequence of elements. Elements can added and removed only at one end (the top of the stack). • The depth of stack is the number of elements it contains. • An empty stack has depth zero. 6-2 Stack concepts (2) • Illustration (stack of books): Initially: Rob Roy War & Peace Moby Dick After removing a book: War & Peace Moby Dick After adding “Misérables”: After adding “2001”: Misérables War & Peace Moby Dick 2001 Misérables War & Peace Moby Dick 6-3 Stack applications • Interpreter (e.g., the Java Virtual Machine) maintains a stack containing intermediate results during evaluation of complicated expressions also containing arguments and return addresses for method calls and returns. • Parser (e.g., a component of the Java compiler) maintains a stack containing symbols encountered during parsing. 6-4 Example 1: text-file reversal • A text file is a sequence of (zero or more) lines. • To reverse the order of these lines, we must store them in a first-in-last-out sequence. • Text-file reversal algorithm: To output the lines of file in reverse order: 1. Make line-stack empty. 2. For each line read from file, repeat: 2.1. Add line to the top of line-stack. 3. While line-stack is not empty, repeat: 3.1. Remove a line from the top of line-stack into line. 3.2. Output line. 4. Terminate. 6-5 Example 2: bracketing (1) • A phrase is well-bracketed if: for every left bracket, there is a later matching right bracket for every right bracket, there is an earlier matching left bracket the subphrase between a pair of matching brackets is itself wellbracketed. • Examples (mathematical expressions): s (s – a) (s – b) (s – c) (– b + [b2 – 4ac]) / 2a s (s – a) (s – b (s – c) s (s – a) s – b) (s – c) (– b + [b2 – 4ac)] / 2a well-bracketed well-bracketed ill-bracketed ill-bracketed ill-bracketed 6-6 Example 2 (2) • Bracket matching algorithm: To test whether phrase is well-bracketed: 1. Make bracket-stack empty. 2. For each symbol sym in phrase (scanning from left to right), repeat: 2.1. If sym is a left bracket: 2.1.1. Add sym to the top of bracket-stack. 2.2. If sym is a right bracket: 2.2.1. If bracket-stack is empty, terminate with false. 2.2.2. Remove a bracket from the top of bracket-stack into left. 2.2.3. If left and sym are not matched brackets, terminate with false. 3. Terminate with true if bracket-stack is empty, or false otherwise. 6-7 Stack ADT: requirements • Requirements: 1) It must be possible to make a stack empty. 2) It must be possible to add (‘push’) an element to the top of a stack. 3) It must be possible to remove (‘pop’) the topmost element from a stack. 4) It must be possible to test whether a stack is empty. 5) It should be possible to access the topmost element in a stack without removing it. 6-8 Stack ADT: contract (1) • Possible contract, expressed as a Java interface: public interface Stack { // Each Stack object is a stack whose elements are objects. /////////////// Accessors /////////////// public boolean isEmpty (); // Return true if and only if this stack is empty. public Object getLast (); // Return the element at the top of this stack. 6-9 Stack ADT: contract (2) • Possible contract (continued): /////////////// Transformers /////////////// public void clear (); // Make this stack empty. public void addLast (Object elem); // Add elem as the top element of this stack. public Object removeLast (); // Remove and return the element at the top of this stack. } 6-10 Implementation of stacks using arrays (1) • Represent a bounded stack (depth maxdepth) by: variable depth, containing the current depth array elems of length maxdepth, containing the stacked elements in elems[0… depth–1]. topmost element Invariant: 0 1 element element length=0 unoccupied depth–1 depth element maxdepth–1 1 maxdepth–1 Empty stack: Illustration (maxdepth = 6): 1 0 2 Moby War & Rob Dick Peace Roy depth=3 4 5 6-11 Implementation using arrays (2) • Java implementation: public class ArrayStack implements Stack { private Object[] elems; private int depth; /////////////// Constructor /////////////// public ArrayStack (int maxDepth) { elems = new Object[maxDepth]; depth = 0; } 6-12 Implementation using arrays (3) • Java implementation (continued): /////////////// Accessors /////////////// public boolean isEmpty () { return (depth == 0); } public Object getLast () { if (depth == 0) throw …; return elems[depth-1]; } 6-13 Implementation using arrays (4) • Java implementation (continued): /////////////// Transformers /////////////// public void clear () { for (int i = 0; i < depth; i++) elems[i] = null; depth = 0; } public void addLast (Object elem) { if (depth == elems.length) throw …; elems[depth++] = elem; } 6-14 Implementation using arrays (5) • Java implementation (continued): public Object removeLast () { if (depth == 0) throw …; Object topElem = elems[--depth]; elems[depth] = null; return topElem; } } • Analysis: Operations isEmpty, getLast, addLast, removeLast have time complexity O(1). Operation clear has time complexity O(n). 6-15 Implementation of stacks using SLLs (1) • Represent an (unbounded) stack by an SLL, such that the first node contains the topmost element. topmost element Invariant: element element element Empty stack: Illustration: Rob Roy War & Peace Moby Dick 6-16 Implementation using SLLs (2) • Java implementation: public class LinkedStack implements Stack { private SLLNode top; /////////////// Constructor /////////////// public LinkedStack () { top = null; } 6-17 Implementation using SLLs (3) • Java implementation (continued): /////////////// Accessors /////////////// public boolean isEmpty () { return (top == null); } public Object getLast () { if (top == null) throw …; return top.element; } 6-18 Implementation using SLLs (4) • Java implementation (continued): /////////////// Transformers /////////////// public void clear () { top = null; } public void addLast (Object elem) { top = new SLLNode(elem, top); } 6-19 Implementation using SLLs (5) • Java implementation (continued): public Object removeLast () { if (top == null) throw …; Object topElem = top.element; top = top.succ; return topElem; } } • Analysis: All operations have time complexity O(1). 6-20 Stacks in the Java class library • Java provides no Stack interface or class as such. • However, the java.util.LinkedList class provides all the above Stack operations. • Illustration: import java.util.LinkedList; LinkedList bookStack = new LinkedList(); bookStack.addLast("Moby Dick"); bookStack.addLast("War & Peace"); bookStack.addLast("Rob Roy"); System.out.println(bookStack.removeLast()); 6-21 Example 3: text-file reversal revisited (1) • Recall the text-file reversal algorithm of Example 1. • Implementation: public static void reverse ( BufferedReader input, BufferedWriter output) throws IOException { LinkedList lineStack = new LinkedList(); for (;;) { String line = input.readLine(); if (line == null) break; // end of input lineStack.addLast(line); } input.close(); 6-22 Example 3 (2) • Implementation (continued): while (! lineStack.isEmpty()) { String line = lineStack.removeLast(); output.write(line + "\n"); } output.close(); } 6-23