Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Stacks Chapter 5 Chapter Objectives • To learn about the stack data type and how to use its four methods: push, pop, peek, and empty • To understand how Java implements a stack • To learn how to implement a stack using an underlying array or a linked list • To see how to use a stack to perform various applications, including finding palindromes, testing for balanced (properly nested) parentheses, and evaluating arithmetic expressions Chapter 5: Stacks 2 Stack • Dinner plates at a cafeteria • Spring-loaded “stack” of plates • “Push” a new plate onto the stack • “Pop” an existing plate off of the stack • Only the top plate is accessible • “Last-In, First-Out”, or LIFO Chapter 5: Stacks 3 Stack • Pez dispenser also uses a stack • Only the top Pez candy can be accessed • Can only extract one item at a time • “Push” candy onto stack • “Pop” candy off of stack • Only the top candy is accessible, LIFO, etc. Chapter 5: Stacks 4 Stack • Stack might seem to be too restrictive • LIFO • Only one element accessible • Only operations are push, pop, peek, empty • However, stacks are extremely useful in CS • Simple and useful • For example, stacks used when executing programs • Used like “scratch paper” to keep track of info Chapter 5: Stacks 5 Specification of the Stack Abstract Data Type • Only the top element of a stack is visible, therefore the number of operations performed by a stack are few • The only operations available are • Inspect the top element (peek) • Retrieve (and remove) the top element (pop) • Put a new element on the stack (push) • Test for an empty stack (empty) Chapter 5: Stacks 6 Specification of the Stack Abstract Data Type (continued) Chapter 5: Stacks 7 StackInt<E> Interface /** Stack is a LIFO data structure */ public interface StackInt < E > { /** Pushes an item onto the top of the stack and returns the item pushed. */ E push(E obj); /** Returns the object at the top of the stack without removing it. */ E peek(); /** Returns the object at the top of the stack and removes it. */ E pop(); /** Returns true if the stack is empty; otherwise, returns false.*/ boolean empty();} Chapter 5: Stacks 8 Stack Example • Suppose we have a stack called names Trudy Bob Alice • And we execute names.pop(); • What is the return value? • “Trudy” and the stack is Bob Alice Chapter 5: Stacks 9 Stack Example • We now have the stack Bob Alice • And we execute names.push(“Charlie”); • What is the return value? • “Charlie” and stack is Charlie Bob Alice Chapter 5: Stacks 10 Stack Example • We now have the stack Charlie Bob Alice • And we execute names.peek(); • What is the return value? • “Charlie” and stack is Charlie Bob Alice Chapter 5: Stacks 11 Stack Example • We now have the stack Charlie Bob Alice • And we execute names.empty(); • What is return value? • Returns false and stack is Charlie Bob Alice Chapter 5: Stacks 12 Stack Applications • We consider two programs that use stacks • Palindrome finder • Parentheses matcher • First we consider palindrome finder • Palindrome: reads the same in either direction • For example: “level” and “Able was I ere I saw Elba” • Note that we do not ignore spaces and punctuation • So, for example, “never odd or even” not considered a palindrome for this exercise (but often it is) Chapter 5: Stacks 13 Palindrome Finder • Input: string to be tested • Output: message indicating whether string is a palindrome or not • How to slove this problem? • Many different ways to solve this… • For example, could create a new string by going from end to beginning of original string • Then compare new and original strings • If equal, string is a palindrome • But we want to use a stack! Chapter 5: Stacks 14 Palindrome Finder • Using a stack… • Push characters of original string onto stack • Then pop characters off and append to new string • Compare new string and original string • If same, then it is a palindrome • Why does this work? • If we push, then pop, it will reverse string Chapter 5: Stacks 15 Palindrome Finder • Suppose string is “frank” • First, push letters onto stack… frank f frank r f frank a r f frank n a r f Chapter 5: Stacks frank k n a r f 16 Palindrome Finder • Then pop letters off of stack and append to new string… k kn kna knar k n a r f n a r f a r f r f knarf f • Finally, compare original and new string: • We have frank != knarf, so not a palindrome Chapter 5: Stacks 17 Class PalindromeFinder Chapter 5: Stacks 18 Testing PalindromeFinder • What types of strings should be test??? • Single character (which is always a palindrome) • Single words • Both palindromes and non-palindromes • Multiple words • Both palindromes and non-palindromes • Different cases (upper/lower) • Even-length strings • Odd-length strings • Empty string (considered palindrome by default) Chapter 5: Stacks 19 Balanced Parenthesis • It is important to determine whether an expression is “balanced” with respect to parentheses • For example • (a+b*(c/(d-e)))+(d/e) is balanced • But • (a+b*(c/d-e)))+(d/e) is not balanced • Problem is more complicated if braces or brackets (square and/or curly) are also used • Good solution is to use stacks! • Here, we only consider parenthesis Chapter 5: Stacks 20 ParenChecker Class • Input: String (representing an expression) • Output: A message indicating whether expression is balanced with respect to parenthesis or not • Of course, we want to use a stack… • What is the idea behind the algorithm? • Push open parenthesis onto stack • When closed parenthesis is encountered • Try to pop top element off of stack • If no top element (stack is empty), not balanced • When done, if stack is not empty, then not balanced Chapter 5: Stacks 21 ParenChecker Algorithm • • • • • Given expression to test… Create an empty stack of characters Set balanced = true (i.e., assume it is balanced) Set index = 0 While balanced is true and index < expression length • Get the next character in expression • If character in open parenthesis • Push open parenthesis onto stack • Else if character is closing parenthesis • If stack is empty, set balanced to false • Else pop element from stack • Increment index • Return true if balanced is true and stack is empty Chapter 5: Stacks 22 ParenChecker Class Chapter 5: Stacks 23 ParenChecker Testing • • • • What data to test on? Simple valid expressions (one level of matched parens) Simple invalid expressions More complex expressions (valid and invalid) • Test too many open parens and too many closed parens • Know the correct answer before testing an expression Chapter 5: Stacks 24 Implementing a Stack • In Java, Stack class extends Vector • Could also have been implemented using other Lists • Such as ArrayList or LinkedList • Could also be implemented using Array • We’ll look (briefly) at each of these Chapter 5: Stacks 25 Stack as a Vector • The Java API includes a Stack class as part of the package java.util • The Vector class implements a growable array • Elements of a vector accessed using an integer index • Size can grow or shrink as needed to accommodate the adding and removing of elements • In following examples, push letters of “Java” onto stack: a v a J Chapter 5: Stacks 26 Stack as a Vector Chapter 5: Stacks 27 Stack as a Vector • • • • Java Stack is an extension of Vector Therefore, can use all Vector methods on a Stack Is this a good thing? You can access any element of a Vector • So, you can access any element of a Stack • If you try to access elements of a Stack, you might get ArrayIndexOutOfBoundsException • Best to restrict yourself to stack-specific methods Chapter 5: Stacks 28 Stack as a List • Can use ArrayList, Vector, LinkedList classes • Since all implement the List interface • Name of class illustrated in text is ListStack<E> • Note that ListStack is an adapter class • Gives different names to essentially same operations • Also true of Java’s Vector-based implementation • For example, java.util.Stack<E> push is code is public E push(E obj) { add(obj); return obj; } Chapter 5: Stacks 29 ListStack.java public class ListStack < E > implements StackInt < E > { private List < E > theData; public ListStack() { theData = new ArrayList < E > (); } public E push(E obj) { theData.add(obj); return obj; } ... Chapter 5: Stacks 30 Stack as an Array • Allocate storage for an array with an initial default capacity when creating a new stack object • Keep track of the top of the stack, topOfStack • For empty stack, topOfStack is set to -1 • No size method • Array size does not grow/shrink after each push/pop • However, must reallocate if more space needed • This is very primitive • And that’s why I like it best… Chapter 5: Stacks 31 Stack as an Array Chapter 5: Stacks 32 Stack as an Array public class ArrayStack < E > implements StackInt < E > { E[] theData; int topOfStack = -1; private static final int INITIAL_CAPACITY = 10; public ArrayStack() { theData = (E[])new Object[INITIAL_CAPACITY]; } public E push(E obj) { if (topOfStack == theData.length - 1) { reallocate(); } topOfStack++; theData[topOfStack] = obj; return obj; } ... Chapter 5: Stacks 33 Stack as a Linked List • Can implement a stack using a linked list of nodes • See code and details in text Chapter 5: Stacks 34 Comparison of Stack Implementations • Extending a Vector (as is done by Java) is a poor choice • All Vector methods are accessible • Then why does Java do it this way? • What about ArrayList implementation? • Easiest to implement, ArrayList does all of the work… • What about Array implementation? • Slightly more difficult for programmer • What about Linked List implementation? • Uses only as much storage as needed • However, links are essentially wasted • Regardless of method used, push/pop is O(1) Chapter 5: Stacks 35 Stack Application • We consider problem of evaluating math expressions • Postfix and infix notation • Expressions normally written in infix form • Operators (+,-,*,/, etc.) between the operands • Good for humans, not so good for computers • Computers prefer postfix notation • Operands come first, then operators Chapter 5: Stacks 36 Postfix vs Infix Chapter 5: Stacks 37 Postfix Advantages • Advantage of postfix form include • No need for parentheses • No need to consider operator precedence Chapter 5: Stacks 38 Evaluating Postfix Expressions • Problem: Write a class to evaluate postfix expressions. • Analysis: Stack is good data structure to store operands until needed • Design: Class PostfixEvaluator with methods • Method eval: scans postfix expression and processes its tokens • Method evalOp: evaluates each operator • Method isOperator: determine whether a character is an operator Chapter 5: Stacks 39 Evaluating Postfix Expressions Chapter 5: Stacks 40 Evaluating Postfix Expressions Chapter 5: Stacks 41 Evaluating Postfix Expressions Chapter 5: Stacks 42 Converting Infix to Postfix Chapter 5: Stacks 43 Converting Infix to Postfix Chapter 5: Stacks 44 Converting Infix to Postfix Chapter 5: Stacks 45 Converting Infix to Postfix Chapter 5: Stacks 46 Converting Infix to Postfix Chapter 5: Stacks 47 Chapter Review • A stack is a last-in, first-out (LIFO) data structure • A stack is a simple but powerful data structure • Four operations are empty, peek, pop, and push • Stacks are useful to process information in the reverse of the order that it is encountered • In Java, Stack is implemented as an extension of the Vector class Chapter 5: Stacks 48 Chapter Review • We considered 3 different ways to implement a stack: • Using the List interface as a container • Using an array as a container • Using a linked list as a container • We applied stacks to evaluate arithmetic expressions Chapter 5: Stacks 49