Stacks 15-121 Fall 2018 Margaret Reid-Miller
Today Exam 2 is next Tuesday, October 30 Today: Quiz 5 solutions Recursive add from last week (see SinglyLinkedListR.java) Stacks ADT (Queues on Thursday) ArrayStack Application Fall 2018 15-121 (Reid-Miller) 2
Recursive add public void add(e obj) { if (head == null) head = new Node(obj, null); else add(head, obj); } // precondition: list!= null private void add(node list, E obj) { if (list.next == null) list.next = new Node(obj, null); else add(list.next, obj); } Fall 2018 15-121 (Reid-Miller) 3
Elegant Recursive add public void add(e obj) { head = add(head, obj); } private Node add(node list, E obj) { if (list == null) return new Node(obj, null); else list.next = add(list.next, obj); return list; } Fall 2018 15-121 (Reid-Miller) 4
Interlude: ADT vs. Data Structure Abstract Data Types Formal description of the behavior (semantics) of a data type. Our first ADT: List (an ordered sequence of elements that can be accessed by index). Data Structures A concrete representation/organization of data e.g., array, class, ArrayList, LinkedList Fall 2018 15-121 (Reid-Miller) 5
Fall 2018 15-121 (Reid-Miller) 6
Stack ADT last in, first out (LIFO) Operations: PUSH adds an element onto the top of the stack POP removes the element from the top of the stack PEEK returns the element on the top of the stack without removing it (optional operation). Test if the stack is EMPTY Why have a Stack ADT? Less power than arrays or Lists Use them for more discipline, simple, fast operations Fall 2018 15-121 (Reid-Miller) 7
Stack last in, first out (LIFO) Uses: A word processor s undo feature Parenthesis balancing Evaluating subexpressions, like: 2*4 + 6*3 The run-time stack (activation records/stack frames) Fall 2018 15-121 (Reid-Miller) 8
Possible interface for Stack public interface LIFOStack<E> { void push(e obj); E pop(); E peek(); boolean isempty(); } Fall 2018 15-121 (Reid-Miller) 9
Stack Implementations Want O(1) for all operations, so what underlying data structure can we use? array? Yes, if top is last element of array ArrayList? Yes, if top is size()-1 linked list? Yes, with top at head of the list Fall 2018 15-121 (Reid-Miller) 10
Array Implementation fields public class ArrayStack<E> implements LIFOStack<E>{ private E[] dataarray; private int top; } // methods (next slide) Index of top stack element in array Fall 2018 15-121 (Reid-Miller) 11
Array Implementation Constructor & isempty public ArrayStack<E>() { } dataarray = (E[]) new Object[1]; top = ; -1 Indicates an empty stack public boolean isempty() { return ( ); top == -1 } Fall 2018 15-121 (Reid-Miller) 12
Array Implementation push public void push(e obj) { } if ( ) top == dataarray.length()-1 reallocate(); top = top + 1; dataarray[top] = obj; Fall 2018 15-121 (Reid-Miller) 13
Array Implementation pop // Complete pop method public E pop() { if ( ) throw new EmptyStackException(); } Fall 2018 15-121 (Reid-Miller) 14
Array Implementation pop public E pop() { } if (top < 0) throw new EmptyStackException(); E obj = dataarray[top]; dataarray[top] == null; top--; return obj; Fall 2018 15-121 (Reid-Miller) 15
Array Implementation peek public E peek() { if (top < 0) } throw new EmptyStackException(); return dataarray[top]; Fall 2018 15-121 (Reid-Miller) 16
Nested Parentheses Goal: Determine if a string containing a mathematical expression is nested correctly. Parenthetical symbols include {}, [], (). Algorithm: Process the expression from left to right. If left parenthetical symbol, push it on the stack. If right parenthetical symbol, pop the stack to see if it is a matching left parenthetical symbol. If not, the parenthetical nesting is invalid. When done processing, if the stack is empty, the parenthetical nesting is valid. Fall 2018 15-121 (Reid-Miller) 17
Examples Fall 2018 15-121 (Reid-Miller) 18
RPN (Postfix Notation) Some modern calculators use Reverse Polish Notation (RPN) Developed in 1920 by Jan Lukasiewicz Can write mathematical formulas without using parentheses. Example: 5 * ( 6 + 7 ) becomes in RPN: 5 6 7 + * Fall 2018 15-121 (Reid-Miller) 19
Evaluating postfix with a stack Note: Assume the postfix expression is valid. Each entry in a postfix expression is a token. 1. Let S be an empty stack. 2. For each token in the expression: a. If the token is a number, push it on the stack S. b. Otherwise (the token is an operator): i. Pop a token off stack S and store it in y. ii. Pop a token off stack S and store it in x. iii. Evaluate x operator y. iv. Push result on stack S. 3. Pop the stack for the final answer. Fall 2018 15-121 (Reid-Miller) 20
Evaluating postfix: Example Postfix (RPN): 5 7 + 8 6 - / 3 9 * + Fall 2018 15-121 (Reid-Miller) 21
Converting Infix to Postfix Note: Assume the infix expression is valid. Each entry in a infix expression is a token. 1. Let S be an empty stack. 2. Let postfix be an empty string. 3. For each token in the infix expression: a. If the token is a number, append it to the postfix string. b. Otherwise (the token is an operator) Process the operator (see next 2 slides) 4. While the stack S is not empty: a. Pop an operator off the stack S and append it to the posfix string. Fall 2018 15-121 (Reid-Miller) 22
Processing the operators (converting infix to postfix, cont d) Each operator has a precedence. *, / multiplicative higher precedence +, - additive lower precedence Operators of the same precedence are evaluated left to right Assign precedence values to each operator. Operator * Precedence 2 / 2 + 1-1 Fall 2018 15-121 (Reid-Miller) 23
Process the operator (converting infix to postfix, cont d) Let nextop be the operator token. 1. If stack S is empty, push nextop on stack S. 2. Otherwise: a. Let topop = peek(s). b. If prec(nextop) > prec(topop), push nextop on stack S. c. Otherwise: i. While S is not empty and prec(nextop) prec(topop): a) Let topop = pop(s). b) Append topop to postfix string. c) If stack S is not empty, let topop = peek(s). ii. Push nextop on stack S. Fall 2018 15-121 (Reid-Miller) 24
Converting: An example Infix: 5 + 4 * 3 / 2-1 Fall 2018 15-121 (Reid-Miller) 25
Processing Parentheses (converting infix to postfix, cont d) Each pair of parentheses marks a subexpression that must be completely converted before previous operators are processed. Assign the lowest precedence to left and right parentheses so only a right parenthesis can pop off a left parenthesis. Do not put parentheses in the postfix string. Operator Precedence * 2 / 2 + 1-1 ( -1 ) -1 Fall 2018 15-121 (Reid-Miller) 26
Process the operator - revised (converting infix to postfix, cont d) Let nextop be the operator token. 1. If stack S is empty or nextop is (, push nextop on stack S. 2. Otherwise: a. Let topop = peek(s). b. If prec(nextop) > prec(topop), push nextop on stack S. c. Otherwise: i. While S is not empty and prec(nextop) prec(topop): a) Let topop = pop(s). b) If topop is (, exit loop immediately. c) Append topop to postfix string. d) If stack S is not empty, let topop = peek(s). ii. If nextop is not ), push nextop on stack S. Fall 2018 15-121 (Reid-Miller) 27
Converting: An example Infix: 7 + 5 * ( 4 / 2 + 1) - 6 Fall 2018 15-121 (Reid-Miller) 28
Invalid expressions Assume that tokens are only operators and integers. Evaluating a postfix expression: How would you know that the postfix expression is not valid? Converting an infix expression to postfix: How would you know that the infix expression is not valid? Fall 2018 15-121 (Reid-Miller) 29