240 likes | 427 Views
A Stack as an Abstract Data Type. A stack Last-in, first-out ( LIFO ) property The last item placed on the stack will be the first item removed Analogy A stack of dishes in a cafeteria vs: A queue First in, first out ( FIFO ) property The first item added is the first item to be removed.
E N D
A Stack as an Abstract Data Type • A stack • Last-in, first-out (LIFO) property • The last item placed on the stack will be the first item removed • Analogy • A stack of dishes in a cafeteria • vs: A queue • First in, first out (FIFO) property • The first item added is the first item to be removed Stack of cafeteria dishes (vertical slice view)
15.1 – Stacks Adding an element Removingan element Top of stack
Developing the Stack ADT • ADT stack operations • Create an empty stack • Determine whether a stack is empty • Add a new item to the stack • Remove from the stack the item that was added most recently • Retrieve (but not remove) from the stack the item that was added most recently
public interface StackInterface<E> { /** Determines whether stack is empty. */ publicboolean isEmpty(); /** Adds an item to the top of a stack. */ publicvoid push(E newItem); /** Removes the top of a stack. * Exception: Throws StackException if the stack is empty. */ public E pop() throwsStackException; /** Retrieves the top of a stack. * Exception: Throws StackException if the stack is empty. */ public E peek() throwsStackException; }
Simple Example importjava.util.*; // For Java’s Stack class publicclassStackTest { public staticvoid main (String[] args) { Stack<String> stk = newStack<String>(); stk.push("one"); stk.push("two"); stk.pop(); stk.push("three"); System.out.println("Contents of Stack using toString():" + stk); } } • What does stk contain? • How would we define toString()using only Stack methods?
Printing a Stack without destroying it! /* returns a String representation of the contents of a Stack from top to bottom, assuming that the E on the Stack have the toString() method */ public String toString (Stack<E> stk) { } /* returns a String representation of the contents of a Stack from top to bottom, assuming that the E on the Stack have the toString() method */ public String toString (Stack<E> stk) { // Create a temporary stack to hold contents of stk Stack<E> tempStack = newStack<E>(); String S =”[“; while (!stk.empty()) { E element = stk.pop(); S = S + element.toString() + " “; tempStack.push(element); } S = S + “]”; // restore contents of stk while (!tempStack.empty()) stk.push(tempStack.pop()); } return S; }
Advanced Example: Checking for Balanced Braces • An example of balanced braces • a{b{c}{d{e}}f}g • Examples of unbalanced braces • a{b}} :Too many closing braces • {c{d}e :Too few closing braces • {f(g)h] :Mismatching braces
Checking Balanced Braces: Helper Methods /* returns true if c is an open bracket */ public staticboolean open_bracket (char c) { return (c == '(') || (c == '{') || (c == '[') || (c == '<'); } /* returns true if c is a close bracket */ public staticboolean close_bracket (char c) { return (c == ')') || (c == '}') || (c == ']') || (c == '>'); } /* returns the closing bracket matching the input open bracket */ public staticchar matching_bracket (char c) { if (c == '(') return')'; else if (c == '{') return'}'; else if (c == '[') return']'; else return'>'; }
Checking Balanced Braces Pseudocode while (still more chars to read ) { get next char in the string if it is open_bracket then push it on top of the stack if it is a close_bracket pop char off stack check to see if it matches bracket } What can go wrong?
Checking Balanced Braces Pseudocode Start by declaring input string balanced while (still more chars to read && string still balanced) { get next char in the string if it is open_bracket then push it on top of the stack if it is a close_bracket if stack empty => not balanced pop char off stack check to see if it matches bracket if not matched => not balanced } if stack not empty => not balanced
Checking Balanced Braces /* returns true if the string S has balanced open and closed brackets */ public staticboolean isBalanced (String S) { Stack <Character> stk = newStack <Character>(); int i = 0; boolean balanced = true; char nextC, top; while (balanced && (i < S.length())) { nextC = S.charAt(i); // get the next character in the string if (open_bracket(nextC)) // push open brackets onto the stack stk.push(newCharacter(nextC)); elseif (close_bracket(nextC)) { // check whether the matching open bracket is on top of stack if (stk.empty()) balanced = false; else { top = stk.pop().charValue(); if (nextC != matching_bracket(top)) balanced = false; } } i++; } return (balanced && stk.empty()); } abc{defg{ijk}{l{mn}}op}qr : true [{(<>)}]: true [{(<)>}]: false [{): false
Implementations of the ADT Stack • The ADT stack can be implemented using • An array • A reference-based list • The ADT LinkedList • The ADT Vector • StackInterface • Provides a common specification for the three implementations • StackException • Used by StackInterface • Extends java.lang.RuntimeException
public interface StackInterface<E> { /** Determines whether stack is empty. * Precondition: None. * Postcondition: Returns true if the stack is empty; otherwise returns false. */ publicboolean isEmpty(); /** Adds an item to the top of a stack. * Precondition: newItem is the item to be added. * Postcondition: If insertion is successful, newItem is on top of the stack.*/ publicvoid push(E newItem); /** Removes the top of a stack. * Precondition: None. * Postcondition: If the stack is not empty, the item that was added most * recently is removed from the stack and returned. * Exception: Throws StackException if the stack is empty. */ public E pop() throwsStackException; /** Retrieves the top of a stack. * Precondition: None. * Postcondition: If the stack is not empty, the item that was added most * recently is returned. The stack is unchanged. * Exception: Throws StackException if the stack is empty. */ public E peek() throwsStackException; }
StackException • StackException • Any Java method that implements a stack-using algorithm should do one of the following • Take precautions to avoid an exception • Provide try and catch blocks to handle a possible exception • /******* file StackException.java *******/ • public classStackException • extends java.lang.RuntimeException { • publicStackException(String s) { • super(s);// just let my parent handle it • }// end constructor • } // end StackException
An Array Based Implementation • StackArrayBased class • Implements StackInterface • Instances • Stacks • Private data fields • An array of Objects called items • The index top Figure 6.4 An array-based implementation
public class StackArrayBased<E> implements StackInterface<E> { • private <E> items[]; // Assumes top of stack is at items[0] • publicStackArrayBased() { • publicboolean isEmpty() { • publicvoid push(E newItem) { • public E pop() throwsStackException { • } • public E peek() throwsStackException { • } }
An Implementation that Uses the ADT LinkedList • The ADT LinkedList can be used to represent the items in a stack • How do we implement the stack ADT (e.g., push, pop, peek, etc.) if the elements of the stack are stored in a LinkedList?
public class StackLinkedListBased<E> implements StackInterface<E> { • privateLinkedList<E> items; // Assumes top of stack is at position 0 • publicStackLinkedListBased() { • publicboolean isEmpty() { • publicvoid push(E newItem) { • public E pop() throwsStackException { • } • public E peek() throwsStackException { • } • privateLinkedList<E> items; // Assumes top of stack is at position 0 • publicStackLinkedListBased() { • items = newLinkedList<E>(); } • publicboolean isEmpty() { • return items.isEmpty(); } • publicvoid push(E newItem) { • items.add(0, newItem); } • public E pop() throwsStackException { • if (!isEmpty()) return items.remove(0); • elsethrownewStackException("Stack Exception on pop: stack empty"); • } • public E peek() throwsStackException { • if (!isEmpty()) return items.get(0); • else throw newStackException("Stack Exception on peek: stack empty"); • } }
A Client Program public classStackTest { public staticvoid main(String[] args) { StackLinkedListBased<Integer> stack = newStackLinkedListBased<Integer>(); for (int i=0; i<10; i++) { stack.push(i); } // end for for (int j=0; j<15; j++) { System.out.println(stack.pop()); } // end for } // end main } What’s the problem?
Catching an Exception public classStackTest { public staticvoid main(String[] args) { StackLinkedListBased<Integer> stack = newStackLinkedListBased<Integer>(); for (int i=0; i<10; i++) { stack.push(i); } // end for for (int j=0; j<15; j++) { try { System.out.println(stack.pop()); } catch (StackException ex) { System.out.println(“Empty stack!”); break; } } // end for } // end main } What changes are needed if we do not want to use a LinkedList implementation?
A Reference-Based Implementation • StackReferenceBased • Implements StackInterface • top is a reference to the head of a linked list of items top D C B A
15.5 – The java.util.Stack Class • While it contains operations similar to a classic stack, it contains other differences • java.util.Stackprovides a search operation that attempts to locate a target element returns its distance from the top of the stack • java.util.Stackis based upon the Vectorclass, which supports direct access to elements at specific indices
15.5 – The java.util.Stack Class • The java.util.Stack class was developed mainly as a convenience • Much of the added functionality comes through inheritance and interface implementation • A stack is not everything a Vector is, so it is not a proper is-a relationship • It also violates the premise of a well-designed collection class
Important Application: Execution Stack publicint first(int a, int b) { int c; … a = second(c ); … } publicint second(int f){ int g; … g = third(f,g); … } publicint third(int m, int n){ … return n; } public staticvoid main(String[] args) { int i, j; … System.out.println( first(i,j) ); … } third n m ret second f g ret first a b c ret main i j Remember factorial? What happens when you call fact(500000)?