Stacks
description
Transcript of Stacks
Stacks
Chapter 5
Chapter 5: Stacks 2
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 3
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 4
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 5
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 6
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 7
Specification of the Stack Abstract Data Type (continued)
Chapter 5: Stacks 8
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 9
Stack Example
• Suppose we have a stack called names
Alice
BobTrudy
• And we execute names.pop();• What is the return value?• “Trudy” and the stack is
Alice
Bob
Chapter 5: Stacks 10
Stack Example
• We now have the stack
• And we execute names.push(“Charlie”);• What is the return value? • “Charlie” and stack is
Alice
Bob
Alice
BobCharlie
Chapter 5: Stacks 11
Stack Example
• We now have the stack
• And we execute names.peek();• What is the return value? • “Charlie” and stack is
Alice
BobCharlie
Alice
BobCharlie
Chapter 5: Stacks 12
Stack Example
• We now have the stack
• And we execute names.empty(); • What is return value?• Returns false and stack is
Alice
BobCharlie
Alice
BobCharlie
Chapter 5: Stacks 13
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 14
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 15
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 16
Palindrome Finder
• Suppose string is “frank”• First, push letters onto stack…
f
frank
rf
frank
rf
a
frank
rf
an
frank
rf
ank
frank
Chapter 5: Stacks 17
Palindrome Finder
• Then pop letters off of stack and append to new string…
rf
an
kn
rf
knar
rf
a
kna
f
knarf
rf
ank
k
• Finally, compare original and new string:• We have frank != knarf, so not a palindrome
Chapter 5: Stacks 18
Class PalindromeFinder
Chapter 5: Stacks 19
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 20
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 21
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 22
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 23
ParenChecker Class
Chapter 5: Stacks 24
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 25
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 26
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:
Java
Chapter 5: Stacks 27
Stack as a Vector
Chapter 5: Stacks 28
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 29
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 ispublic E push(E obj) {
add(obj);return obj;
}
Chapter 5: Stacks 30
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 31
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 32
Stack as an Array
Chapter 5: Stacks 33
Stack as an Arraypublic 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 34
Stack as a Linked List
• Can implement a stack using a linked list of nodes• See code and details in text
Chapter 5: Stacks 35
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 36
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 37
Postfix vs Infix
Chapter 5: Stacks 38
Postfix Advantages
• Advantage of postfix form include• No need for parentheses• No need to consider operator precedence
Chapter 5: Stacks 39
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 40
Evaluating Postfix Expressions
Chapter 5: Stacks 41
Evaluating Postfix Expressions
Chapter 5: Stacks 42
Evaluating Postfix Expressions
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
Converting Infix to Postfix
Chapter 5: Stacks 48
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 49
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