200 likes | 778 Views
Stack. Contents. ADT Stack Implementations of ADT Stack Composition using an ArrayList Implementation using an array Applications Checking for matching brackets Expression evaluation. Stack. ADT Stack.
E N D
Stack Contents • ADT Stack • Implementations of ADT Stack • Composition using an ArrayList • Implementation using an array • Applications • Checking for matching brackets • Expression evaluation
Stack ADT Stack A Stack is a constrained List. It is a List that maintains a last-in-first-out discipline. The usual model for describing a Stack is the spring-loaded tray dispenser in a cafeteria. Only the top tray is accessible and the stack is maintained by “pushing” a cleared tray on top of the stacked trays or “popping” the tray on top off of the stack. A stack will have operations push and pop, and observations top, isEmpty and size.
Stack ADT Stack ADT Stack TYPES: Object, Integer, Boolean FUNCTIONS Create: ( ) Stack push: Stack, Object Stack pop: Stack -/-> Stack top: Stack -/-> Object isEmpty: Stack Boolean size: Stack Integer PRECONDITIONS for all s Stack, for all x Object pre-pop(s) ::= !isEmpty(s) pre-top(s) ::= !isEmpty(s)
Stack ADT Stack (cont.) POST-CONDITIONS for all s, s’ Stack, for all x Object post-push(s, x; s’) ::= (size(s’) = size(s) + 1) && (top(s’) = x) post-pop(s; s’) ::= (size(s’) = size(s) – 1) && (top(s’) != top(s)) AXIOMS for all s Stack, x Object isEmpty(Create( )) top(push(s, x)) = x top(pop(push(s, x))) = top(s)) size(push(s, x)) = size(s) + 1 size(pop(s)) = size(s) - 1 The Axioms are a formal way of specifying the “semantics” of an ADT (how each method “behaves”, the Functions indicate the syntax for calling a method. They are listed here as “an aside” to complement their mention in the text Now let’s examine the choices for implementing this ADT
Stack Implementations for ADT Stack • Composition using either an ArrayList or a LinkedList as the private attribute Since inserts and removes are only performed at the back of the list either of these containers will be equally efficient. However since the LinkedList has the additional overhead of storing a handle to an adjacent Node (actually 2 handles for the doubly linked-list implementation) in each of its Nodes, it has double (or triple) the storage requirements of an ArrayList. The better choice is therefore the ArrayList. • Implementing directly with an array The advantage of doing this over composition is that it removes the overhead of a second method call, but if the supplier of this class wants automatic resizing when the array is full, he or she will have to provide it themselves. • Implementing directly using a linked list The need to resize doesn’t pertain, but this approach has the same extra storage requirements as previously stated.
Stack Implementing Stack ADT using Composition with an ArrayList
Use an ArrayList object to hold the data Let the ArrayList buffer do the work! Stack Composition publicclass Stack { private ArrayList buffer; public Stack( ) { buffer = new ArrayList( );} public void push (Object x) { //preconditions: none //post-conditions: x is on top of stack, size incremented buffer.add(x); } public Object pop( ) throws IndexOutOfBoundsException { //preconditions: Stack not empty //post-conditions: top item removed, size decreased by 1 Object rtn = null; rtn = buffer.remove(buffer.size( ) – 1); //ArrayList remove(int loc) throws IndexOutOfBoundsException return rtn; }
Stack Composition (cont.) public Object top( ) throws IndexOutOfBoundsException { //preconditions: Stack not empty //post-condition: no change in state of the Stack Object rtn = null; rtn = buffer.get(buffer.size( ) – 1); //throw IndexOutOfBoundsException back to the client return rtn; } publicboolean isEmpty( ) { return buffer.size( ) == 0; } public int size( ) { return buffer.size( ); } }
Stack Construct a Stack with an array as data member, implementing your own methods.
Maintain an array -- size is both the number contained and the location of next available index Private method to perform resizing Stack Array implementation of a Stack public class Stack { private Object [ ] buffer; private int size, growAmt; private void resize(int newCap) { if ( newCap > buffer.length) { Object [ ] newBuff = new Object[newCap]; for (int i = 0; i < size; i++) newBuff[i] = buffer[i]; buffer = newBuff; } } public Stack ( ) { buffer = new Object[10]; size = 0; growAmt = 10; } public Stack(int cap, int growBy) { buffer = new Object[cap]; size = 0; growAmt = growBy; }
Stack Array implementation publicvoid push(Object x) { //precondition: none //post-conditions: top( ) == x, and size is incremented if (size == buffer.length) resize(size+growthAmt); buffer[i] = x; size++; } public Object pop( ) throws StackEmptyException { //precondition: Stack not empty //post-condition: top object removed from stsack, size decremented Object rtn = null; if (size > 0) { --size; rtn = buffer[size]; } else thrownew StackEmptyException( ); return rtn; } Write your own StackException class (that extends Exception) Method top( ) is implemented similarly, returning buffer[size-1] and not decrementing size.
Stack Applications
Stack Application – Balanced brackets Consider the string {int i = 0; while (i < size) { if (A[i] == key) {flag = true;} else{flag=false;} i++;}} This is the kind of string one may encounter in a Java program. One of the requirements for this being a well-formed string is that the left and right braces balance out. We will use a stack to write a function to determine whether the left and right braces in a string are balanced.
Stack Application – matched brackets publicboolean matchedBraces (String str) { StringBuffer strb = new StringBuffer(str); //Need to look at individual chars Stack braces = new Stack (10, 5); //Using the Stack with array imp. int stop = strb.length( ); for (int i = 0; i < stop; i++) { try{ if (strb.charAt(i) ==‘{‘) braces.push(new Character(‘{‘)); elseif (strb.charAt(i) == ‘}’) if (braces.isEmpty( )) return false; else braces.pop( ); }catch (Exception e) {e.printStackTrace(System.err);} return braces.isEmpty( ); } Note! What you push onto the stack is irrelevant. We just want to check if number of pushes and pops are equal.
Stack Infix to Postfix Expression Evaluator
Building an Arithmetic Expression Evaluator Infix and Postfix Expressions: Assume 1-digit integer operands and the binary operators + - * / only Infix Expression Properties: Usual precedence and associativity of operators Parentheses used to subvert precedence Postfix Expression Properties: Both operands of binary operators precede operator Parentheses no longer needed Infix Expression Equivalent Postfix Expression 3*4+5 34*5+ 3*(4+5)/2 345+*2/ (3+4)/(5-2) 34+52-/ 7-(2*3+5)*(8-4/2) 723*5+842/-*- 3-2+1 32-1+
Building an Arithmetic Expression Evaluator value of expression at top of stack Assume 1-digit integer operands, the binary operators + - * / only, and the string to be evaluated is properly formed Postfix Expression String Processing Rules for processing the postfix string: Starting from the left hand end, inspect each character of the string 1. if it’s an operand – push it on the stack 2. if it’s an operator – remove the top 2 operands from the stack, perform the indicated operation, and push the result on the stack An Example:3*(4+5)/2 345+*2/ 13 Remaining Postfix String int Stack (top) Rule Used 345+*2/ empty 45+*2/ 3 1 5+*2/ 3 4 1 +*2/ 3 4 5 1 *2/ 3 9 2 2/ 27 2 / 27 2 1 null 13 2
Building an Arithmetic Expression Evaluator Infix to Postfix Conversion Assume 1-digit integer operands, the binary operators + - * / only, and the string to be converted is properly formed Rules for converting the infix string: Starting from the left hand end, inspect each character of the string 1. if it’s an operand – append it to the postfix string 2. if it’s a ‘(‘ – push it on the stack 3. if it’s an operator – if the stack is empty, push it on the stack else pop operators of greater or equal precedence and append them to the postfix string, stopping when a ‘(‘ is reached, an operator of lower precedence is reached, or the stack is empty; then push the operator on the stack 4. if it’s a ‘)’ – pop operators off the stack, appending them to the postfix string, until a ‘(‘ is encountered and pop the ‘(‘ off the stack 5. when the end of the infix string is reached – pop any remaining operators off the stack and append them to the postfix string
Infix to Postfix Conversion (continued) An Example: 7-(2*3+5)*(8-4/2) 723*5+842/-*- Remaining Infix String char Stack Postfix String Rule Used 7-(2*3+5)*(8-4/2) empty null -(2*3+5)*(8-4/2) empty 7 1 (2*3+5)*(8-4/2) - 7 3 2*3+5)*(8-4/2) -( 7 2 *3+5)*(8-4/2) -( 72 1 3+5)*(8-4/2) -(* 72 3 +5)*(8-4/2) -(* 723 3 5)*(8-4/2) -(+ 723* 3 )*(8-4/2) -(+ 723*5 1 *(8-4/2) - 723*5+ 4 (8-4/2) -* 723*5+ 3 8-4/2) -*( 723*5+ 2 -4/2) -*( 723*5+8 1 4/2) -*(- 723*5+8 3 /2) -*(- 723*5+84 1 2) -*(-/ 723*5+84 3 ) -*(-/ 723*5+842 1 null empty 723*5+842/-*- 4&5
Building an Arithmetic Expression Evaluator node Stack InfixToPostfix PostfixExpressionEvaluator InToEval Putting It All Together: Object Model Diagram