490 likes | 600 Views
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
E N D
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
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
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
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
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
Specification of the Stack Abstract Data Type (continued) Chapter 5: Stacks
StackInt<E> Interface /** Stack is a LIFO data structure */ publicinterface 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
Alice Bob Trudy Alice Bob Stack Example • Suppose we have a stack called names • And we execute names.pop(); • What is the return value? • “Trudy” and the stack is Chapter 5: Stacks
Alice Bob Alice Bob Charlie Stack Example • We now have the stack • And we execute names.push(“Charlie”); • What is the return value? • “Charlie” and stack is Chapter 5: Stacks
Alice Bob Charlie Alice Bob Charlie Stack Example • We now have the stack • And we execute names.peek(); • What is the return value? • “Charlie” and stack is Chapter 5: Stacks
Alice Bob Charlie Alice Bob Charlie Stack Example • We now have the stack • And we execute names.empty(); • What is return value? • Returns false and stack is Chapter 5: Stacks
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
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
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
frank frank frank frank frank r r f r f a k f a n r f a n f Palindrome Finder • Suppose string is “frank” • First, push letters onto stack… Chapter 5: Stacks
k kna knar knarf kn k n r f a n r r f a f r f a f Palindrome Finder • Then pop letters off of stack and append to new string… • Finally, compare original and new string: • We have frank != knarf, so not a palindrome Chapter 5: Stacks
Class PalindromeFinder Chapter 5: Stacks
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
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
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
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
ParenChecker Class Chapter 5: Stacks
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
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
a v a J 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: Chapter 5: Stacks
Stack as a Vector Chapter 5: Stacks
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
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
ListStack.java publicclass 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
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
Stack as an Array Chapter 5: Stacks
Stack as an Array publicclass ArrayStack < E > implements StackInt < E > { E[] theData; int topOfStack = -1; privatestaticfinalint 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
Stack as a Linked List • Can implement a stack using a linked list of nodes • See code and details in text Chapter 5: Stacks
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
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
Postfix vs Infix Chapter 5: Stacks
Postfix Advantages • Advantage of postfix form include • No need for parentheses • No need to consider operator precedence Chapter 5: Stacks
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
Evaluating Postfix Expressions Chapter 5: Stacks
Evaluating Postfix Expressions Chapter 5: Stacks
Evaluating Postfix Expressions Chapter 5: Stacks
Converting Infix to Postfix Chapter 5: Stacks
Converting Infix to Postfix Chapter 5: Stacks
Converting Infix to Postfix Chapter 5: Stacks
Converting Infix to Postfix Chapter 5: Stacks
Converting Infix to Postfix Chapter 5: Stacks
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
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