Stacks Introduction Applications Implementations Complex Applications Ch 6

  • Slides: 21
Download presentation
Stacks § § Introduction Applications Implementations Complex Applications

Stacks § § Introduction Applications Implementations Complex Applications

Ch. 6 Stacks § § A stack is a Last-In/First-Out linear data structure: a

Ch. 6 Stacks § § A stack is a Last-In/First-Out linear data structure: a data item is inserted into or taken out of a sequence of elements only at one end of the sequence. This end is called the top of the stack The stack ADT (public prototypes) is the same for different types of data, other than the type difference. So, although we discuss the Object stack, we can get an ADT for a stack of another type by replacing Object with the desired type

Public prototypes of Generic Stack § Constructor public Stack ( ) /* initialize an

Public prototypes of Generic Stack § Constructor public Stack ( ) /* initialize an empty stack */ § Inquiry into the stack public boolean is. Empty ( ) /* Determine whether this stack is empty */ (continues on next page)

Public prototypes of Object. Stack (continued from previous page) public E peek ( )

Public prototypes of Object. Stack (continued from previous page) public E peek ( ) /* return the top item of the stack without removing it from the stack */ public int size( ) /* return the current number of items in this stack */

Public prototypes of Double. Stack § Adding an item public void push (E item)

Public prototypes of Double. Stack § Adding an item public void push (E item) /* add the given item to the top of this stack */ § Removing (and getting) an item public E pop ( ) /* remove and return the top item of this stack */

Think about using a stack § The last-in/First-out and no-storage-restriction properties of a stack

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

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

Example - verify balance of parentheses § The following method checks if the sequence of characters given that is supposed to be an arithmetic expression has balanced left and right parentheses of 3 kinds: ( ), { }, [ ]. Only parentheses are inspected, for full pairing: public static boolean is. Balanced (String expression) { final char LEFT_NORMAL = ‘(‘; final char RIGHT_NORMAL = ‘)’; final char LEFT_CURLY = ‘{‘; (continues on next page)

Example - verify balance of parentheses (continued from previous page) final char RIGHT_CURLY =

Example - verify balance of parentheses (continued from previous page) final char RIGHT_CURLY = ‘}’; final char LEFT_SQUARE = ‘[‘; final char RIGHT_SQUARE = ‘]’; Stack <Character> store = new Stack<Character>; boolean failed = false; for (int i = 0; !failed && i < expression. length( ); i++) { (continues on next page)

Example - verify balance of parentheses (continued from previous page) switch (expression. char. At(i)

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

Example - verify balance of parentheses (continued from previous page) if (store. is. Empty(

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

Example - verify balance of parentheses (continued from previous page) case RIGHT_SQUARE: if (store.

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

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

Example - a method to carry out an arithmetic operation from stack data § In this method two numbers and one operator is taken out of a given numbers stack and a given operators stack to execute and the result number is pushed back to the numbers stack. This method is part of an algorithm to evaluate a fully parenthesized arithmetic expression: public static void evaluate. Stack. Tops (Stack <Double> numbers, Stack <Character>operations) { if (numbers. size ( ) <2) || operations. is. Empty( ) ) throw new Illegal. Argument. Exception (“Wrong Exp”); (continues on next page)

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

Example - a method to carry out an arithmetic operation from stack data (continued from previous page) double operand 2 = numbers. pop ( ); double operand 1 = numbers. pop ( ); switch (operations. pop ( ) ) { case ‘+’: numbers. push (operand 1 + operand 2); break; case ‘-’ : numbers. push (operand 1 - operand 2); break; (continues on next page)

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

Example - a method to carry out an arithmetic operation from stack data (continued from previous page) case ‘*’: numbers. push (operand 1 * operand 2); break; case ‘/’: if (operand 2 == 0) throw new Illegal. Argument. Exception ( Division by zero. ”); numbers. push (operand 1 / operand 2); break; (continues on next page)

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

Example - a method to carry out an arithmetic operation from stack data (continued from previous page) default: throw new Illegal. Argument. Exception ( “Character not a valid operator. ”); } /* end switch */ } /* end method */ Notice that a method like this in a simple loop is not sufficient to evaluate an arithmetic expression, without a more elaborate algorithm: there is operator and parenthesis precedence!

Arithmetic expressions § The arithmetic expressions we usually see and write are called Infix

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

The Postfix expression § – – Here we discuss the evaluation rules of Postfix

The Postfix expression § – – Here we discuss the evaluation rules of Postfix expressions. A pseudo-code is on Page 336 of Textbook. Rules for Prefix expressions are equally simple and can be found on Page 334 Inspect the sequence of numbers and operators from left to right Whenever an operator is encountered, look back for the two most recent numbers past, use the second most recent as the left operand the most recent as the right operand, and place the result into the past sequence as the most recent

Evaluate general arithmetic expressions § § A general arithmetic expression can be evaluated directly

Evaluate general arithmetic expressions § § A general arithmetic expression can be evaluated directly or can be converted to a Postfix expression first for (possibly later) evaluation Assuming the expression has only binary operators (an operator with left and right operands), an algorithmic scheme to convert a fully parenthesized arithmetic expression, using an operators stack, is as follows: (continues on next page)

Convert (fully parenthesized) Infix expressions to Postfix § – – Repeat: getting next item

Convert (fully parenthesized) Infix expressions to Postfix § – – Repeat: getting next item from sequence, it is a left parenthesis: push it into stack to wait for the corresponding right parenthesis number: send it to the output sequence operator: push it into stack to let its right operand ( which may be a parenthesized expression in itself) processed and sent to output first right parenthesis: pop an item from stack (should be an operator) and write it to output; pop another (should be a left parenthesis) and discard

Time analysis of Postfix conversion for fully balanced Infix expression § – – The

Time analysis of Postfix conversion for fully balanced Infix expression § – – The algorithm consists of the following 4 kinds of operations (each is assumed at unit cost), each kind takes O(n) time total, for an expression of n numbers, operations and parentheses altogether Reading the sequence: each item is read once from the sequence and its kind determined Arithmetic operations: there are no more than n operations Stack push: at most n operators , once each Stack pop: at most n operators, once each

Conversion to Postfix for non-fullyparenthesized Infix expressions § • The case of non-fully parenthesized

Conversion to Postfix for non-fullyparenthesized Infix expressions § • The case of non-fully parenthesized Infix expression is more complicated: Without full parentheses, an operator (say, ‘+’) with a number to its right may not operate on the number directly, because there may be an operator to the right of this number with higher precedence (say, ‘/’). In this case, at the soonest the number should be first divided by another number farther on the right side of ‘/’ before the result is operated on by this ‘+’; but then there may be even more ‘/’ or ‘x’ next