Stacks Chapter 5
Overview Motivating the Stack ADT The stack ADT Exceptional situations Stack implementations stacks in Java
Motivating the Stack ADT Netbeans shows you your mistakes e.g. when you use } instead of ) to close a ( if (a < 10} how does it do that? Notice the (s, [s and {s as they appear… …and match each with a ), ] or } (this.setValues(new String[]{“a”, “b”, “c”}))
Operations As each (, [ or { comes in As each ), ] or } comes in: remember it (put on top of stack) – “push” it As each ), ] or } comes in: compare to most recent unmatched – at “top” make sure it’s the same kind forget it (take it off the stack) – “pop” it The last one in is the first one out “LIFO” – Last In, First Out
What is a Stack? Linear pile of objects of one type Real life stacks one on top of another; not a “heap” in a particular order access only at one end (the “top”) “LIFO”: Last In = First Out Real life stacks stack of books/paper stack of plates/bowls/beer cups
Stack Operations Stacks require at least these operations: insert at top .push(item) delete from top .pop() Typically have some others inspect top element .peek() check if empty .isEmpty() empty it out .clear() get number of elements .size()
A Stack Generally arranged up & down “topˮ at the top generally only see the top element Old items are popped off the stack myStack.pop() New items are pushed onto the stack myStack.push(14) Top 35 24 81 12 5 7 17 8 Stack
A Stack Generally arranged up & down “topˮ at the top generally only see the top element Old items are popped off the stack myStack.pop() New items are pushed onto the stack myStack.push(14) Top 24 81 12 5 7 17 8 Stack
A Stack Generally arranged up & down “topˮ at the top generally only see the top element Old items are popped off the stack myStack.pop() New items are pushed onto the stack myStack.push(14) Top 14 24 81 12 5 7 17 8 Stack
Exercise Draw the stacks that result from the following operations. Start with empty each time. Also, make a list of the items popped. push A, push B, push C, pop, push D, pop, pop push 1, push 2, pop, pop, push 3, push 4, pop push 1, push 2, push 3, push 4, pop, pop, pop, pop
Return Values Push naturally void Top naturally value-returning put this thing on the stack; nothing to return Top naturally value-returning return value that is on top of stack Empty naturally boolean (empty or not?) Clear naturally void Size naturally value-returning number of items in the stack
Return Values Pop can be either void or value-returning either: take something off stack and discard it C++’s STL stack is like this or: take something off stack and return it Java’s java.util.Stack (and java.util.Deque) like this Pop must return value if no top operation otherwise no way to get values out of the stack! we (text authors and I) prefer value-returning
Exceptional Circumstances What could go wrong? try to remove/look at top of empty stack try to add to a full stack try to add null to stack (is this wrong?) Options to deal are same as with bags return false (if naturally void) return special value (if one is available) throw exception
Design Decisions Push is naturally void have it return false for failure? have it throw an exception? Top is naturally value-returning have it return null for failure? Pop can be either! boolean/null/exception all valid options!
Exceptions: Checked or Not? Client can easily check if stack is empty there’s a method for that Client can thus write code that will never try to pop/peek on empty stack Client should not be made to deal with exceptions Use unchecked (Runtime) exceptions NOTE: some designers may disagree!
Unchecked Excns & Interfaces Unchecked exceptions don’t need to be mentioned in the interface If they are mentioned, they may be ignored! implementing classes don’t need to throw them NOTE: checked exceptions cannot be ignored Interface should specify them anyway at least in the javadoc! clients should know what to expect
More Design Decisions Provide multiple versions? methods must have different names can’t have different parameters! pair names in some way two versions return null? two versions throw exceptions? How many different versions? don’t want things to be too complex
Two Versions of Each Method Push operation: push throws IllegalState/NullPointer Exception offer returns true/false Pop operation: pop throws NoSuchElementException poll returns null when stack is empty Top operation: get throws a NoSuchElementException peek returns null when the stack is empty
My Stack Interface public interface MyStackInterface<T> { public boolean isEmpty(); // versions throwing exceptions public void push(T newEntry); public T pop(); public T get(); // top // versions returning a special value public boolean offer(T newEntry); // push public T poll(); // pop public T peek(); // top }
Other Stack Interfaces/Classes StackInterface (from Text) java.util.Deque (*) void push(T newEntry); // nothing! T pop(); // throws EmptyStackExcn. T peek(); void push(T newEntry); // throws IllegalStateExcn. // throws ClassCastExcn. // throws NullPointerExcn. // throws IllegalArgumentExcn. T pop(); // throws NoSuchElementExcn. T peek(); // may return null (class) java.util.Stack T push(T newEntry); // nothing T pop(); // throws EmptyStackExcn. T peek(); (*) Deque is preferred to Stack! Names match my interface
Using Stacks Balancing brackets Pre/postfix expressions Conversion to pre/postfix from infix (“normal”) Procedure Activation Records Towers of Hanoi Railway shunting Circuit design Equivalence classes Maze tracing
Balancing Brackets Want to know if a string has the right number of closing brackets/parentheses/etc. Each closing item must match opening item ] for [, ) for (, etc. Nesting may be involved “{a(1, 2), b([c, d]), {e, f, [(g), ((h))]}}” “(1, [2, 3, ([4, (5, 6), {7,8})])])”
Method Scan the string one character at a time Return false if: stack up opening brackets as you see them when you see a closing bracket, pop a bracket off the top & make sure it matches Return false if: try to pop from an empty stack popped bracket doesn’t match procedure ends with non-empty stack
Note: match must return false when first argument is null Pseudo-Code for i 1 .. Length(string) if isOpenBracket(string[i]) stack.push(string[i]); else if isCloseBracket(string[i]) if ~match(stack.peek(), string[i]) return false; stack.pop(); return stack.isEmpty(); Note: match must return false when first argument is null
{a(1, 2), b([c, d]), {e, f, [(g), ((h))]}} Trace Execution “{a(1, 2), b([c, d]), {e, f, [(g), ((h))]}}” {a(1, 2), b([c, d]), {e, f, [(g), ((h))]}} ( [ { ( [ { ( [ { ( [ { [ ( { [ { [ { [ { ( { ( { ( { { { { { { { { ( ) ( [ ] ) { [ ( ) ( ( ) ) ] } } Stack is empty: return true
Mismatch: return false Trace Execution “(1, [2, 3, ([4, (5, 6), {7,8})])])” (1, [2, 3, ([4, (5, 6), {7,8})])]) ( [ { [ ( [ ( [ ( [ ( Mismatch: return false ( [ [ ( ( ( [ ( [ ( ) { } )
Exercise Trace the balancing method for the following string: (1 + (12 * [1, 3, 5], )) [, 7, 87, ][]()){()}
Postfix Calculator AKA Reverse Polish notation No need for parentheses used on HP calculators No need for parentheses (3 + 5)*(8 + 17*6) becomes 3 5 + 8 17 6 * + * Number, enter, number, operation 5 (enter) 17 (times) [85 appears]
Method Numbers get pushed Operators: pop top two elements do math according to operation push result
Trace Execution 3 5 + 8 17 6 * + * 6 17 8 17 8 102 8 5 3 8 110 8 3 8 880 3 5 + 8 17 6 * + * (3 + 5)*(8 + 17*6) = 8*(8 + 102) = 8*110 = 880
Exercise Evaluate the following post-fix expression 1 2 3 4 5 + * + * 10 / show your stack show the equivalent infix expression
Conversion to Postfix Write down operators & operations the way they need to be done used to compile expressions (3 + 5)*(8 + 17*6) 3+5 first 3, 5, + 17*6 next 17, 6, * 8 + (17*6) 8, 17, 6, *, + multiply above 3, 5, +, 8, 17, 6, *, +, *
Things to Note (3 + 5)*(8 + 17*6) 3 5 + 8 17 6 * + * order of operations 17*6 instead of 8 + 17 parentheses 3+5 instead of 5*8 numbers written down in same order Need to keep operations pending next operation may need to be done before it closing parenthesis complete all ops since (
Trace of Conversion (3 + 5) * (8 + 17 * 6 – 2) * + ( + ( * + ( * – ( * \0 3 5 8 17 6 2
Exercise Write pseudo-code for the infix to postfix conversion what functions would be useful? get a token check if number/operator/bracket so and use them!
Stack Implementations Can use arrays or linked structures Top is the important location for arrays it’s at the back (of the used part) for linked structures it’s at the front No access to middle elements if you need access to the middle, then you shouldn’t be using a stack!
Stacks in Java Use Deque instead of Stack import and declare (like Lists, Sets, Bags, …) import java.util.Deque; import java.util.ArrayDeque; Deque<String> stack = new ArrayDeque<String>(); Deques have more operations than stacks use only the Stack operations! push/pop may throw exceptions peek may return null
Questions