Stacks - Naval Postgraduate Schoolfaculty.nps.edu/kmsquire/cs3901/section2/notes/04a_Stacks.pdf ·...

Preview:

Citation preview

Stacks

Stacks & Queues

• A linear sequence, or list, is an ordered collection of elements:

S = (s1, s2, ... , sn) �

• Stacks and queues are finite linear sequences.

• A Stack is a LIFO (Last In First Out) list.

• A Queue is a FIFO (First In First Out) list.

ADT Stack

Inserting and deleting elements occurs at the top of Stack S

bottom

top

Stack S

Stack Operations

myStack

myStack = new Stack( );

top

myStack

myStack.push(ape);

apemyStack

myStack.push(eel);

apeeel

top

myStack

pet = myStack.pop();

apetop

myStack

boolean empty =myStack.isEmpty();

apetop

top

Java NPSStack ADT

/*** This interface defines the Stack ADT*/

public interface NPSStack<E> {

public void clear( );

public boolean isEmpty( );

public E peek( ) throws NPSStackEmptyException;

public E pop( ) throws NPSStackEmptyException;

public void push(E element);

public int size( );}

Defining the Stack ADT

• Array Implementation– How should we represent an empty stack?

– ADT Stack does not overflow. How should we handle an array overflow?

• Linked List Implementation– How should we represent an empty stack?

ArrayStack Implementation

public class NPSArrayStack<E> implements NPSStack<E> {

/** Default initial size of an array */private static final int DEFAULT_SIZE = 25;

/** An array to store the elements */private E[] element;

/** The number of elements in the stack. */private int count;

//----------------------------------

/** Default constructor */public NPSArrayStack( ) {

this(DEFAULT_SIZE);}

/** Creates a stack with an initial capacity of size */public NPSArrayStack( int size ) {

element = (E[]) new Object[size];count = 0;

}

ArrayStack Implementation

/** Removes all elements from the stack. */public void clear( ) {

//// May or may not be desired (why?)////for (int i = 0; i < count; i++ ) {// element[i] = null;//}

count = 0;}

/** Determines whether the stack is empty or not. */public boolean isEmpty( ) {

return (count == 0);}

/** Returns the number of elements in the stack */public int size( ) {

return count;}

ArrayStack Implementation

/** Returns the top-of-stack element without removing it */public E peek( ) throws NPSStackEmptyException {

if (isEmpty( )) {throw new NPSStackEmptyException( );

} else {return element[count-1];

}}

/** Removes the top-of-stack element. */public E pop( ) throws NPSStackEmptyException {

if (isEmpty( )) {throw new NPSStackEmptyException( );

} else {return element[--count];

}}

/** Adds an element to the stack. */public void push(E element) {

if (count == this.element.length) {expand( );

}this.element[count++] = element;

}

ArrayStack Implementation

/** Returns the top-of-stack element without removing it */public E peek( ) throws NPSStackEmptyException {

if (isEmpty( )) {throw new NPSStackEmptyException( );

} else {return element[count-1];

}}

/** Removes the top-of-stack element. */public E pop( ) throws NPSStackEmptyException {

E topElement = peek( );count--;

return topElement;

}

/** Adds an element to the stack. */public void push(E element) {

if (count == this.element.length) {expand( );

}this.element[count++] = element;

}

This (private) method is leftas an exercise.

Stack with a Singly Linked List

• We can implement a stack with a singly linked list• The top element is stored at the first node of the list• The space used is O(n) and each operation of the

Stack ADT takes O(1) time• Left as an exercise

∅∅∅∅t

nodes

elements

Applications of Stacks

• Direct applications– Page-visited history in a Web browser– Undo sequence in a text editor– Chain of method calls in the Java Virtual Machine– Parenthesis matching– HTML/XML Tag Matching– Evaluating arithmetic expressions (more later)

• Indirect applications– Auxiliary data structure for algorithms– Component of other data structures

Method Stack in the JVM

• The Java Virtual Machine (JVM) keeps track of the chain of active methods with a stack

• When a method is called, the JVM pushes on the stack a frame containing– Local variables and return value– Program counter, keeping track of

the statement being executed

• When a method ends, its frame is popped from the stack and control is passed to the method on top of the stack

• Allows for recursion

main() {int i = 5;foo(i);}

foo(int j) {int k;k = j+1;bar(k);}

bar(int m) {…}

barPC = 1m = 6

fooPC = 3j = 5k = 6

mainPC = 2i = 5

Example: Parentheses Matching

• Each “(”, “{”, or “[” must be paired with a matching “)”, “}”, or “[”

– correct: ( )(( )){([( )])}– correct: ((( )(( )){([( )])}– incorrect: )(( )){([( )])}– incorrect: ({[ ])}– incorrect: (

Parentheses Matching Algorithm

Algorithm ParenMatch(X,n):

Input: An array X of n tokens, each of which is either a grouping symbol, a

variable, an arithmetic operator, or a number

Output: true if and only if all the grouping symbols in X match

Let S be an empty stack

for i=0 to n-1 do

if X[i] is an opening grouping symbol then

S.push(X[i])

else if X[i] is a closing grouping symbol then

if S.isEmpty() then

return false {nothing to match with}

if S.pop() does not match the type of X[i] then

return false {wrong type}

if S.isEmpty() then

return true {every symbol matched}

else

return false {some symbols were never matched}

Example: HTML/XML Tag Matching

<body><center><h1> The Little Boat </h1></center><p> The storm tossed the littleboat like a cheap sneaker in anold washing machine. The threedrunken fishermen were used tosuch treatment, of course, butnot the tree salesman, who even asa stowaway now felt that hehad overpaid for the voyage. </p><ol><li> Will the salesman die? </li><li> What color is the boat? </li><li> And what about Naomi? </li></ol></body>

The Little Boat

The storm tossed the little boatlike a cheap sneaker in an oldwashing machine. The threedrunken fishermen were used tosuch treatment, of course, but notthe tree salesman, who even asa stowaway now felt that he hadoverpaid for the voyage.

1. Will the salesman die?2. What color is the boat?3. And what about Naomi?

• For fully-correct HTML, each <name> should pair with a matching </name>

Evaluating Arithmetic Expressions

• Write a program to evaluate arithmetic expressions such as

4.5 + sin 45 * ( 334 - 0.34 ^ 2)

• Overall approach:– Input an infix arithmetic expression

– Convert it into postfix format (use Stack here)

– Evaluate the postfix expression (use another Stack here)

– Output the result

Three Formats for Expressions

Infix: operand operator operand4 + 5

Postfix: operand operand operator4 5 +

Prefix: operator operand operand+ 4 5

Infix and Postfix Expressions

3.4 + 22 * 98

((3 - 4 ) * 3 ) ^ (2 / 0.33)

4 + 5 * 3 - 2

(4 + 5) * 3 - 2

3.4 22 98 * +

3 4 - 3 * 2 0.33 / ^

4 5 3 * + 2 -

4 5 + 3 * 2 -

Infix Postfix

• Postfix expressions have no parentheses.• Relative order of the operands are the same in infix and

and postfix expressions

Infix-to-Postfix Algorithm

• General Idea:– Scan the input for tokens (operators and operands).

– If the token is an operand, output it (or append it to the output string) �

– If the token is an operator i, compare it with the top of stack operator s.

• If i has a lower priority than s, pop and output s.

• Repeat this comparison until you locate s that has a lower priority than i.

• Push i onto the stack.

– At the end of the input, pop and output everything on the stack (or append it to the output string, etc.)

Infix-to-Postfix Algorithm

• Example: 4 + 5 * 3

• There are five tokens: three operands and two operators.

• Operator * has a higher priority than +.

• Output is 4 5 3 * +

• When the next token is *

* 3

+

3

*+* is stacked

because its priorityis higher than +

Sample Process

4 + 5 * 3

Next Token:

Output:

Stack Content:

+ 5 * 3 5 * 3

+

* 3

+

3

*+

*+

pop twice

4 4 4 5 4 5 4 5 3 4 5 3 * +

Algorithm

public static String convertInfixToPostfix(String infix) {

StringBuffer postfix = new StringBuffer();Stack<String> operatorStack = new Stack<String>();StringTokenizer st = new StringTokenizer(infix);String nextToken;

Set<String> operators = opPrecedence.keySet();

while (st.hasMoreTokens()) {nextToken = st.nextToken();

if (!operators.contains(nextToken)) {postfix.append(nextToken + " ");

}else {// it is an Operator, another subclass of Token

while (!operatorStack.isEmpty()&& opPrecedence.get(operatorStack.peek()) >=

opPrecedence.get(nextToken))postfix.append(operatorStack.pop() + " ");

operatorStack.push(nextToken);}

}

// Pop off remaining operatorswhile (!operatorStack.isEmpty())

postfix.append(operatorStack.pop() + " ");

return postfix.toString();}

Recommended