0% found this document useful (0 votes)
34 views60 pages

ch03 Stacks

Uploaded by

Özcan Akay
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)
34 views60 pages

ch03 Stacks

Uploaded by

Özcan Akay
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/ 60

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) { private static final String OPEN = "([{";
// Create an empty stack.
Stack<Character> s = new Stack<Character>(); private static final String CLOSE = ")]}";
boolean balanced = true;
try { private static boolean isOpen(char ch) {
int index = 0; return OPEN.indexOf(ch) > -1;
while (balanced && index < expression.length()) { }
char nextCh = expression.charAt(index);
if (isOpen(nextCh)) { private static boolean isClose(char ch) {
s.push(nextCh); return CLOSE.indexOf(ch) > -1;
} 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());
}
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
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
38
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
39
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;
int topOfStack = -1;
private static final int INITIAL_CAPACITY = 10; Keep track of the top of the
stack (subscript of the
element at the top of the
@SupressWarnings("unchecked") stack; for empty stack = -1)
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
topOfStack = -1 302
1
[4] = null value = 'a'
[5] = null
[6] = null
[7] = null Character
[8] = null
public E push(E obj) { [9] = null
if (topOfStack == theData.length - 1){ value = 'v'
reallocate();
}
topOfStack++; Character
theData[topOfStack] = obj;
return obj; value = 'a'
}
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
It is easiest
inserts to
a node
insertatand
the
when the list is empty,
delete
head andfrom
popthedeletes
head of thea
pop returns null
node atlist
the head
Implementing a Stack as a Linked
45
Data Structure (cont.)
import java.util.NoSuchElementException;

/** Class to implement interface StackInt<E> as a linked list. public E pop() {


*/ if (isEmpty()) {
public class LinkedStack<E> implements StackInt<E> { throw new NoSuchElementException();
private Node<E> topOfStackRef = null; } else {
E result = topOfStackRef.data;
public E push(E obj) { topOfStackRef = topOfStackRef.next;
topOfStackRef = new Node<>(obj, topOfStackRef); return result;
return obj; }
} }
public E peek() {
if (isEmpty()) {
throw new NoSuchElementException();
} else {
return topOfStackRef.data;
}
}
public boolean isEmpty() {
return topOfStackRef == null;
}
}
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 -
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 -
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
58
(cont.)
import java.util.*; public static int eval(String expression) throws SyntaxErrorException {
// Create an empty stack.
/** Class that can evaluate a postfix expression. */ Deque<Integer> operandStack = new ArrayDeque<>();
public class PostfixEvaluator { // Process each token.
private static final String OPERATORS = "+- String[] tokens = expression.split("\\s+");
*/"; try {
private static int evalOp(char op, Deque<Integer> for (String nextToken : tokens) {
operandStack) { char firstChar = nextToken.charAt(0);
// Pop the two operands off the stack. // Does it start with a digit?
int rhs = operandStack.pop(); if (Character.isDigit(firstChar)) {
int lhs = operandStack.pop(); // Get the integer value.
int result = 0; int value = Integer.parseInt(nextToken);
// Evaluate the operator. // Push value onto operand stack.
switch (op) { operandStack.push(value);
case '+' : result = lhs + rhs; } // Is it an operator?
break; else if (isOperator(firstChar)) {
case '-' : result = lhs - rhs; // Evaluate the operator.
break; int result = evalOp(firstChar, operandStack);
case '/' : result = lhs / rhs; // Push result onto the operand stack.
break; operandStack.push(result);
case '*' : result = lhs * rhs; } else {
break; // Invalid character.
} throw new SyntaxErrorException("Invalid character encountered: " + firstChar);
return result; }
} } // End for.
private static boolean isOperator(char ch) { // No more tokens - pop result from operand stack.
return OPERATORS.indexOf(ch) != -1;
}
Evaluating Postfix Expressions
59
(cont.)
int answer = operandStack.pop();
// Operand stack should be empty.
if (operandStack.isEmpty()) {
return answer;
} else {
// Indicate syntax error.
throw new SyntaxErrorException("Syntax Err");
}
} catch (NoSuchElementException ex) {
// Pop was attempted on an empty stack.
throw new SyntaxErrorException("Syntax Err");
}
}
}
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
62
(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
67
(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