21
Stacks Stacks Introduction Introduction Applications Applications Implementations Implementations Complex Complex Applications Applications

Stacks Introduction Applications Implementations Complex Applications

Embed Size (px)

Citation preview

StacksStacks

IntroductionIntroduction ApplicationsApplications ImplementationsImplementations Complex ApplicationsComplex Applications

Ch. 6 StacksCh. 6 Stacks

A stack is a Last-In/First-Out linear data structure: A stack is a Last-In/First-Out linear data structure: a data item is inserted into or taken out of a a data item is inserted into or taken out of a sequence of elements only at one end of the sequence of elements only at one end of the sequence. This end is called the top of the stacksequence. This end is called the top of the stack

The stack ADT (public prototypes) is the same for The stack ADT (public prototypes) is the same for different types of data, other than the type different types of data, other than the type difference. So, although we discuss the Object difference. So, although we discuss the Object stack, we can get an ADT for a stack of another stack, we can get an ADT for a stack of another type by replacing Object with the desired typetype by replacing Object with the desired type

Public prototypes of Generic StackPublic prototypes of Generic Stack

ConstructorConstructor public Stack ( )public Stack ( ) /* initialize an empty stack *//* initialize an empty stack */

Inquiry into the stackInquiry into the stack public boolean isEmpty ( )public boolean isEmpty ( ) /* Determine whether this stack is empty *//* Determine whether this stack is empty */

(continues on next page)(continues on next page)

Public prototypes of ObjectStackPublic prototypes of ObjectStack

(continued from previous page)(continued from previous page)

public E peek ( )public E peek ( ) /* return the top item of the stack without removing it /* return the top item of the stack without removing it

from the stack */from the stack */

public int size( )public int size( ) /* return the current number of items in this stack *//* return the current number of items in this stack */

Public prototypes of DoubleStackPublic prototypes of DoubleStack

Adding an itemAdding an item public void push (E item)public void push (E item) /* add the given item to the top of this stack *//* add the given item to the top of this stack */

Removing (and getting) an itemRemoving (and getting) an item public E pop ( )public E pop ( ) /* remove and return the top item of this stack *//* remove and return the top item of this stack */

Think about using a stackThink about using a stack

The last-in/First-out and no-storage-restriction The last-in/First-out and no-storage-restriction properties of a stack makes it a good candidate properties of a stack makes it a good candidate data structure for implementing the kind of data structure for implementing the kind of processing where data come in sequence and need processing where data come in sequence and need to be stored until certain conditions are met and to be stored until certain conditions are met and then taken out to process, and where the more then taken out to process, and where the more recent data should be retrieved and processed firstrecent data should be retrieved and processed first

Example - verify balance of parenthesesExample - verify balance of parentheses The following method checks if the sequence of characters The following method checks if the sequence of characters

given that is supposed to be an arithmetic expression has given that is supposed to be an arithmetic expression has balanced left and right parentheses of 3 kinds: ( ), { }, [ ] . balanced left and right parentheses of 3 kinds: ( ), { }, [ ] . Only parentheses are inspected, for full pairing:Only parentheses are inspected, for full pairing:

public static boolean isBalanced (String expression) {public static boolean isBalanced (String expression) { final char LEFT_NORMAL = ‘(‘;final char LEFT_NORMAL = ‘(‘; final char RIGHT_NORMAL = ‘)’;final char RIGHT_NORMAL = ‘)’; final char LEFT_CURLY = ‘{‘;final char LEFT_CURLY = ‘{‘;

(continues on next page)(continues on next page)

Example - verify balance of parenthesesExample - verify balance of parentheses (continued from previous page)(continued from previous page) final char RIGHT_CURLY = ‘}’;final char RIGHT_CURLY = ‘}’; final char LEFT_SQUARE = ‘[‘;final char LEFT_SQUARE = ‘[‘; final char RIGHT_SQUARE = ‘]’;final char RIGHT_SQUARE = ‘]’;

Stack <Character> store = new Stack<Character>;Stack <Character> store = new Stack<Character>; boolean failed = false;boolean failed = false; for (int i = 0; !failed && i < expression.length( ); i++)for (int i = 0; !failed && i < expression.length( ); i++) { {

(continues on next page)(continues on next page)

Example - verify balance of parenthesesExample - verify balance of parentheses (continued from previous page)(continued from previous page) switch (expression.charAt(i) ) {switch (expression.charAt(i) ) { case LEFT_NORMAL: /* falling through to next */case LEFT_NORMAL: /* falling through to next */ case LEFT_CURLY: /* falling through to next */case LEFT_CURLY: /* falling through to next */ case LEFT_SQUARE:case LEFT_SQUARE: store.push (expression.charAt(i) );store.push (expression.charAt(i) ); break;break; case RIGHT_NORMAL:case RIGHT_NORMAL: (continues on next page)(continues on next page)

Example - verify balance of parenthesesExample - verify balance of parentheses (continued from previous page)(continued from previous page) if (store.isEmpty( ) || store.pop( ) !=if (store.isEmpty( ) || store.pop( ) != LEFT_NORMAL)LEFT_NORMAL) failed = true;failed = true; break;break; case RIGHT_CURLY:case RIGHT_CURLY: if (store.isEmpty( ) || store.pop( ) != if (store.isEmpty( ) || store.pop( ) != LEFT_CURLY)LEFT_CURLY) failed = true;failed = true; break;break; (continues on next page)(continues on next page)

Example - verify balance of parenthesesExample - verify balance of parentheses (continued from previous page)(continued from previous page) case RIGHT_SQUARE:case RIGHT_SQUARE: if (store.isEmpty( ) || store.pop( ) !=if (store.isEmpty( ) || store.pop( ) != LEFT_SQUARE)LEFT_SQUARE) failed = true;failed = true; break;break; } /* end switch */} /* end switch */ } /* end loop */} /* end loop */ return (store.isEmpty( ) && !failed);return (store.isEmpty( ) && !failed); }}

Example - a method to carry out an Example - a method to carry out an arithmetic operation from stack dataarithmetic operation from stack data

In this method two numbers and one operator is taken out of In this method two numbers and one operator is taken out of a given numbers stack and a given operators stack to a given numbers stack and a given operators stack to execute and the result number is pushed back to the execute and the result number is pushed back to the numbers stack. This method is part of an algorithm to numbers stack. This method is part of an algorithm to evaluate a fully parenthesized arithmetic expression:evaluate a fully parenthesized arithmetic expression:

public static void evaluateStackTops (Stack <Double>public static void evaluateStackTops (Stack <Double> numbers, Stack <Character>operations) {numbers, Stack <Character>operations) { if (numbers.size ( ) <2) || operations.isEmpty( ) )if (numbers.size ( ) <2) || operations.isEmpty( ) ) throw new IllegalArgumentException (“Wrong Exp”);throw new IllegalArgumentException (“Wrong Exp”);

(continues on next page)(continues on next page)

Example - a method to carry out an Example - a method to carry out an arithmetic operation from stack dataarithmetic operation from stack data (continued from previous page)(continued from previous page) double operand2 = numbers.pop ( ); double operand2 = numbers.pop ( ); double operand1 = numbers.pop ( ); double operand1 = numbers.pop ( );

switch (operations.pop ( ) ) {switch (operations.pop ( ) ) { case ‘+’: numbers.push (operand1 + operand2);case ‘+’: numbers.push (operand1 + operand2); break;break; case ‘-’ : numbers.push (operand1 - operand2);case ‘-’ : numbers.push (operand1 - operand2); break;break; (continues on next page)(continues on next page)

Example - a method to carry out an Example - a method to carry out an arithmetic operation from stack dataarithmetic operation from stack data

(continued from previous page)(continued from previous page) case ‘*’: numbers.push (operand1 * operand2);case ‘*’: numbers.push (operand1 * operand2); break;break; case ‘/’: if (operand2 == 0)case ‘/’: if (operand2 == 0) throw new IllegalArgumentException (throw new IllegalArgumentException ( Division by zero.”);Division by zero.”); numbers.push (operand1 / operand2);numbers.push (operand1 / operand2); break;break; (continues on next page)(continues on next page)

Example - a method to carry out an Example - a method to carry out an arithmetic operation from stack dataarithmetic operation from stack data

(continued from previous page)(continued from previous page) default: throw new IllegalArgumentException (default: throw new IllegalArgumentException ( “ “Character not a valid operator.”);Character not a valid operator.”); } /* end switch */} /* end switch */ } /* end method */} /* end method */

Notice that a method like this in a simple loop is Notice that a method like this in a simple loop is not sufficient to evaluate an arithmetic expression, not sufficient to evaluate an arithmetic expression, without a more elaborate algorithm: there is without a more elaborate algorithm: there is operator and parenthesis precedence! operator and parenthesis precedence!

Arithmetic expressionsArithmetic expressions

The arithmetic expressions we usually see and The arithmetic expressions we usually see and write are called Infix expressions: an operator is write are called Infix expressions: an operator is in-between the two operands. It is somewhat in-between the two operands. It is somewhat complicated to evaluate because of operator and complicated to evaluate because of operator and parenthesis precedence. There are two other kinds parenthesis precedence. There are two other kinds of expression that are much easier to evaluate if of expression that are much easier to evaluate if the sequence of numbers and operators is already the sequence of numbers and operators is already written or has been converted to that form: the written or has been converted to that form: the Prefix expression and the Postfix expressionPrefix expression and the Postfix expression

The Postfix expressionThe Postfix expression

Here we discuss the evaluation rules of Postfix expressions. Here we discuss the evaluation rules of Postfix expressions. A pseudo-code is on Page 336 of Textbook. Rules for A pseudo-code is on Page 336 of Textbook. Rules for Prefix expressions are equally simple and can be found on Prefix expressions are equally simple and can be found on Page 334Page 334

– Inspect the sequence of numbers and operators from left to Inspect the sequence of numbers and operators from left to rightright

– Whenever an operator is encountered, look back for the two Whenever an operator is encountered, look back for the two most recent numbers past, use the second most recent as the most recent numbers past, use the second most recent as the left operand and the most recent as the right operand, and left operand and the most recent as the right operand, and place the result into the past sequence as the most recentplace the result into the past sequence as the most recent

Evaluate general arithmetic expressionsEvaluate general arithmetic expressions

A general arithmetic expression can be evaluated A general arithmetic expression can be evaluated directly or can be converted to a Postfix expression directly or can be converted to a Postfix expression first for (possibly later) evaluationfirst for (possibly later) evaluation

Assuming the expression has only binary operators (an Assuming the expression has only binary operators (an operator with left and right operands), an algorithmic operator with left and right operands), an algorithmic scheme to convert a fully parenthesized arithmetic scheme to convert a fully parenthesized arithmetic expression, using an operators stack, is as follows: expression, using an operators stack, is as follows:

(continues on next page)(continues on next page)

Convert (fully parenthesized) Infix Convert (fully parenthesized) Infix expressions to Postfixexpressions to Postfix

Repeat: getting next item from sequence, it is aRepeat: getting next item from sequence, it is a– left parenthesis: push it into stack to wait for the left parenthesis: push it into stack to wait for the

corresponding right parenthesiscorresponding right parenthesis– number: send it to the output sequencenumber: send it to the output sequence– operator: push it into stack to let its right operand operator: push it into stack to let its right operand

( which may be a parenthesized expression in itself) ( which may be a parenthesized expression in itself) processed and sent to output firstprocessed and sent to output first

– right parenthesis: pop an item from stack (should be an right parenthesis: pop an item from stack (should be an operator) and write it to output; pop another (should be a operator) and write it to output; pop another (should be a left parenthesis) and discardleft parenthesis) and discard

Time analysis of Postfix conversion for Time analysis of Postfix conversion for fully balanced Infix expressionfully balanced Infix expression

The algorithm consists of the following 4 kinds of The algorithm consists of the following 4 kinds of operations (each is assumed at unit cost), each kind operations (each is assumed at unit cost), each kind takes O(n) time total, for an expression of n numbers, takes O(n) time total, for an expression of n numbers, operations and parentheses altogetheroperations and parentheses altogether

– Reading the sequence: each item is read once from the Reading the sequence: each item is read once from the sequence and its kind determinedsequence and its kind determined

– Arithmetic operations: there are no more than n Arithmetic operations: there are no more than n operationsoperations

– Stack push: at most n operators , once eachStack push: at most n operators , once each– Stack pop: at most n operators, once eachStack pop: at most n operators, once each

Conversion to Postfix for non-fully-Conversion to Postfix for non-fully-parenthesized Infix expressionsparenthesized Infix expressions

The case of non-fully parenthesized Infix expression is The case of non-fully parenthesized Infix expression is more complicated:more complicated:

• Without full parentheses, an operator (say, ‘+’) with a Without full parentheses, an operator (say, ‘+’) with a number to its right may not operate on the number number to its right may not operate on the number directly, because there may be an operator to the right directly, because there may be an operator to the right of this number with higher precedence (say, ‘/’). In this of this number with higher precedence (say, ‘/’). In this case, at the soonest the number should be first divided case, at the soonest the number should be first divided by another number farther on the right side of ‘/’ by another number farther on the right side of ‘/’ before the result is operated on by this ‘+’; but then before the result is operated on by this ‘+’; but then there may be even more ‘/’ or ‘x’ nextthere may be even more ‘/’ or ‘x’ next