0% found this document useful (0 votes)
15 views61 pages

ch03 Stacks

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views61 pages

ch03 Stacks

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

CHAPTER 3

Stacks
Chapter Objectives
 To learn about the stack data type and how to use its four methods:
 push

 pop

 peek

 empty

 To understand how Java implements a stack


 To learn how to implement a stack using an underlying array or
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
Stack Abstract Data Type
Section 3.1
Stack Abstract Data Type
 A stack is one of the most commonly used
data structures in computer science
 A stack can be compared to a Pez
dispenser
 Only the top item can be accessed
 You can extract only one item at a time

 The top element in the stack is the last


added to the stack (most recently)
 The stack’s storage policy is Last-In, First-
Out, or LIFO
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
 We need the ability to
 test for an empty stack (empty)
 inspect the top element (peek)
 retrieve the top element (pop)
 put a new element on the stack (push)
Specification of the Stack Abstract
6
Data Type (cont.)
public interface StackInt<E> {
/* comments are deleted */
E push(E obj);
E peek();
E pop();
boolean empty();
}
A Stack of Strings

 “Rich” is the oldest element on the stack and “Jonathan” is


the youngest (Figure a)
 String last = names.peek(); stores a reference
to “Jonathan” in last
 String temp = names.pop(); removes “Jonathan”
and stores a reference to it in temp (Figure b)
 names.push(“Philip”); pushes “Philip” onto the
stack (Figure c)
Stack Applications
Section 3.2
Balanced Parentheses
 When analyzing arithmetic expressions, it is
important to determine whether an expression is
balanced with respect to parentheses
( a + b * ( c / ( d – e ) ) ) + ( d / e )

 The problem is further complicated if braces or


brackets are used in conjunction with parentheses
 The solution is to use stacks!
Balanced Parentheses (cont.)
Balanced Parentheses (cont.)
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

( ( w * [ x + y ] / z )

balanced : true
index : 0
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

( ( w * [ x + y ] / z )

balanced : true
index : 1
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

( ( w * [ x + y ] / z )

balanced : true
index : 2
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

(
[ ( w * [ x + y ] / z )
(

balanced : true
index : 3
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

[ ( w * [ x + y ] / z )
(

balanced : true
index : 4
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

[ ( w * [ x + y ] / z )
(

balanced : true
index : 5
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

[ ( w * [ x + y ] / z )
(

balanced : true
index : 6
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

(
[ ( w * [ x + y ] / z )
(

Matches!
Balanced still true

balanced : true
index : 7
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

( ( w * [ x + y ] / z )

balanced : true
index : 8
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

( ( w * [ x + y ] / z )

balanced : true
index : 9
Balanced Parentheses (cont.)
Expression: (w * [x + y] / z)

0 1 2 3 4 5 6 7 8 9 10

( ( w * [ x + y ] / z )

Matches!
Balanced still true

balanced : true
index : 10
Balanced Parentheses (cont.)
public static boolean isBalanced(String expression) {
// Create an empty stack.
Stack<Character> s = new Stack<Character>();
boolean balanced = true;
try {
int index = 0;
while (balanced && index < expression.length()) {
char nextCh = expression.charAt(index);
if (isOpen(nextCh)) {
s.push(nextCh);
} else if (isClose(nextCh)) {
char topCh = s.pop();
balanced =
OPEN.indexOf(topCh) == CLOSE.indexOf(nextCh);
}
index++;
}
} catch (EmptyStackException ex) {
balanced = false;
}
return (balanced && s.empty());
}
Balanced Parentheses (cont.)
private static final String OPEN = "([{";

private static final String CLOSE = ")]}";

private static boolean isOpen(char ch) {


return OPEN.indexOf(ch) > -1;
}

private static boolean isClose(char ch) {


return CLOSE.indexOf(ch) > -1;
}
Testing
 Provide a variety of input expressions displaying the result
true or false
 Try several levels of nested parentheses
 Try nested parentheses where corresponding parentheses
are not of the same type
 Try unbalanced parentheses
 No parentheses at all!

 PITFALL: attempting to pop an empty stack will throw an


EmptyStackException. You can guard against this by either
testing for an empty stack or catching the exception
Testing (cont.)
34

 Listing 3.3 (ParenChecker.java, pages 159 - 160)

public static void main(String args[]) {


String expression = JOptionPane.showInputDialog(
"Enter an expression containing parentheses");
if (ParenChecker.isBalanced(expression)) {
JOptionPane.showMessageDialog(null, expression
+ " is balanced");
} else {
JOptionPane.showMessageDialog(null, expression
+ " is not balanced");
}
System.exit(0);
}
Implementing a Stack
Section 3.3
Implementing a Stack as an
Extension of Vector

 The Java API includes a Stack


class as part of the package
java.util :

public class Stack<E> extends Vector<E>

 The Vector class implements a growable array


of objects
 Elements of a Vector can be accessed using an
integer index and the size can grow or shrink as
needed to accommodate the insertion and removal of
elements
Implementing a Stack as an
Extension of Vector (cont.)
 We can use Vector's add method to implement push:
public E push(obj E) {
add(obj);
return obj;
}

 pop can be coded as


public E pop throws EmptyStackException {
try {
return remove (size() – 1);
} catch (ArrayIndexOutOfBoundsException ex) {
throw new EmptyStackException();
}
}
Implementing a Stack as an
Extension of Vector (cont.)
 Because a Stack is a Vector, all of Vector
operations can be applied to a Stack (such as
searches and access by index)
 But, since only the top element of a stack should be
accessible, this violates the principle of information
hiding
Implementing a Stack with a List
Component
 As an alternative to a stack as an extension of Vector, we can write a
class, ListStack, that has a List component (in the example below,
theData)
 We can use either the ArrayList, Vector, or the LinkedList classes,
as all implement the List interface. The push method, for example, can
be coded as

public E push(E obj) {


theData.add(obj);
return obj;
}

 A class which adapts methods of another class by giving different names to


essentially the same methods (push instead of add) is called an adapter
class
 Writing methods in this way is called method delegation
Implementing a Stack with a List
40
Component (cont.)
public class ListStack<E> implements StackInt<E> {
private List<E> theData;

public ListStack() {
theData = new ArrayList<E>();
}

@Override
public E push(E obj) {
theData.add(obj);
return obj;
}

@Override
public E peek() {
if (empty()) {
throw new EmptyStackException();
}
return theData.get(theData.size() - 1);
}
. . . .
Implementing a Stack with a List
41
Component (cont.)
public class ListStack<E> implements StackInt<E> {
private List<E> theData;

. . . .

@Override
public E pop() {
if (empty()) {
throw new EmptyStackException();
}
return theData.remove(theData.size() - 1);
}

@Override
public boolean empty() {
return theData.size() == 0;
}
}
Implementing a Stack Using an Array

 If we implement a stack as an array,


we would need . . . Allocate storage for an
array with a default
capacity
public class ArrayStack<E> implements StackInt<E> {
private E[] theData; Keep track of the top of the
stack (subscript of the element
int topOfStack = -1;
at the top of the stack; for
private static final int INITIAL_CAPACITY = 10;
empty stack = -1)

@SupressWarnings("unchecked")
public ArrayStack() {
theData = (E[])new Object[INITIAL_CAPACITY];
} There is no size variable or method
Implementing a Stack Using an Array
(cont.)
Character
Object[]
value = 'J'
ArrayStack [0] = null
[1] = null
[2] = null Character
theData =
[3] = null
3
0
1
2
topOfStack = -1
[4] = null value = 'a'
[5] = null
[6] = null
[7] = null Character
[8] = null
[9] = null
value = 'v'
public E push(E obj) {
if (topOfStack == theData.length - 1){
Character
reallocate();
}
topOfStack++; value = 'a'
theData[topOfStack] = obj;
return obj;
}
Implementing a Stack Using an Array
(cont.)
@Override
public E pop() {
if (empty()) {
throw new EmptyStackException();
}
return theData[topOfStack--];
}
Implementing a Stack as a Linked
Data Structure
 We can also implement a stack using a linked list of
nodes

push inserts a node at the


It is easiest
when the list to insert and
is empty, pop
head and pop deletes the
delete from the head
returns null of a list
node at the head
Implementing a Stack as a Linked
47
Data Structure (cont.)
 Listing 3.5 (LinkedStack.java, pages 168 - 169)
Comparison of Stack
Implementations
 Extending a Vector (as is done by Java) is a poor
choice for stack implementation, since all Vector
methods are accessible
 The easiest implementation uses a List component
(ArrayList is the simplest) for storing data
 An underlying array requires reallocation of space when the
array becomes full, and
 an underlying linked data structure requires allocating
storage for links
 As all insertions and deletions occur at one end, they are
constant time, O(1), regardless of the type of
implementation used
Additional Stack Applications
Section 3.4
Additional Stack Applications
 Postfix and infix notation
 Expressions normally are written in infix form, but
 it easier to evaluate an expression in postfix form since
there is no need to group sub-expressions in parentheses
or worry about operator precedence
Evaluating Postfix Expressions
 Write a class that evaluates a postfix expression
 Use the space character as a delimiter between
tokens
Evaluating Postfix Expressions (cont.)

4 7 * 20 -
4

1. create an empty stack of integers


2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

4 7 * 20 -
4
7
4
1. create an empty stack of integers
2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

4 * 7 4 7 * 20 -
7

4
1. create an empty stack of integers
2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

28 4 7 * 20 -
28

1. create an empty stack of integers


2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

4 7 * 20 -
28
20

28
1. create an empty stack of integers
2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

28 - 20 4 7 * 20 -
20

28
1. create an empty stack of integers
2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

8 4 7 * 20 -
8

1. create an empty stack of integers


2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)

4 7 * 20 -
8

1. create an empty stack of integers


2. while there are more tokens
3. get the next token
4. if the first character of the token is a digit
5. push the token on the stack
6. else if the token is an operator
7. pop the right operand off the stack
8. pop the left operand off the stack
9. evaluate the operation
10. push the result onto the stack
11. pop the stack and return the result
Evaluating Postfix Expressions (cont.)
60

 Listing 3.6 (PostfixEvaluator.java, pages 173


- 175)
Evaluating Postfix Expressions (cont.)
 Testing: write a driver which
 creates a PostfixEvaluator object
 reads one or more expressions and report the result
 catches PostfixEvaluator.SyntaxErrorException
 exercises each path by using each operator
 exercises each path through the method by trying different
orderings and multiple occurrences of operators
 tests for syntax errors:
 an operator without any operands
 a single operand
 an extra operand
 an extra operator
 a variable name
 the empty string
Converting from Infix to Postfix
 Convert infix expressions to postfix expressions
 Assume:
 expressions consists of only spaces, operands, and operators
 space is a delimiter character
 all operands that are identifiers begin with a letter or underscore
 all operands that are numbers begin with a digit
Converting from Infix to Postfix
63
(cont.)
 Example: convert
w – 5.1 / sum * 2
to its postfix form
w 5.1 sum / 2 * -
Converting from Infix to Postfix
(cont.)
Converting from Infix to Postfix
(cont.)
Converting from Infix to Postfix
(cont.)
Converting from Infix to Postfix
(cont.)
Converting from Infix to Postfix
68
(cont.)
 Listing 3.7 (InfixToPostfix.java, pages 181 -
183)
Converting from Infix to Postfix
(cont.)
 Testing
 Use enough test expressions to satisfy yourself that the
conversions are correct for properly formed input
expressions
 Use a driver to catch
InfixToPostfix.SyntaxErrorException

 Listing 3.8 (TestInfixToPostfix.java, page


184)
Converting Expressions with
Parentheses
 The ability to convert expressions with parentheses
is an important (and necessary) addition
 Modify processOperator to push each
opening parenthesis onto the stack as soon as it is
scanned
 When a closing parenthesis is encountered, pop
off operators until the opening parenthesis is
encountered
 Listing 3.9 (InfixToPostfixParens.java, pages
186 - 188)

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy