VIEWS: 7 PAGES: 30 POSTED ON: 3/20/2013 Public Domain
Stacks and Queues A Maze Define a m × p maze as 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 follows: 1 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 A two-dimensional array 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 with height = m+2 and 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 width = p+2. 1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 To avoid boundary 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 condition, the maze is 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 surround by 1’s. 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 For 1 ≦i ≦m and 1 ≦j ≦p, 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 Walk: maze[i][j] == 0. 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 Wall: If maze[i][j] == 1. 1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Mazing Problem Determine whether there exists a path from the entrance maze[1][1] to the exit maze[m][p]. 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 entrance 1 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 exit 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Allowable Moves For we are at (i, j), there are eight possible directions we can move forward. NW N NE [i-1][j-1] [i-1][j] [i-1][j+1] W [i][j-1] x [i][j+1] E [i][j] The position (i, j) is marked X [i+1][j-1] [i+1][j] [i+1][j+1] when it is visited. SW S SE Allowable Moves Table of moves q offset on i Offset on j move[q].a move[q].b 0 N -1 0 class offsets 1 NE -1 1 { public: 2 E 0 1 int a, b; 3 SE 1 1 }; enum directions {N, NE, E, SE, S, SW, W, NW}; 4 S 1 0 offsets move[8]; 5 SW 1 -1 6 W 0 -1 7 NW -1 -1 Program 3.16 maze: mark: to mark visited positions 0 1 2 3 4 5 6 7 Stack 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 2 1 0 0 0 1 1 0 0 0 0 0 0 3 0 1 1 0 0 0 0 0 0 0 0 0 4 1 1 0 1 1 1 0 0 0 0 0 0 5 1 1 0 0 0 0 0 0 0 0 0 0 6 0 1 1 1 0 0 0 0 0 0 0 0 7 (1, 1, E) < i, j, nextDir. > Initial State Program 3.16 maze: mark: 0 1 2 3 4 5 6 7 Stack 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 2 1 0 0 0 1 1 0 0 0 0 0 0 1 1 3 0 1 1 0 0 0 0 0 0 0 0 0 4 1 1 0 1 1 1 0 0 0 0 0 0 (1, 5, SW) 5 1 1 0 0 0 0 0 0 0 0 0 0 (1, 4, E) 6 0 1 1 1 0 0 0 0 0 0 0 0 (1, 3, E) (2, 2, NE) 7 (1, 1, E) < i, j, nextDir. > (1, 1, E) → (1, 2) Wall (1, 1, SE) → (2, 2) Walk Move forward Can walk? (not wall and not visited) Program 3.16 maze: mark: 0 1 2 3 4 5 6 7 Stack 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 2 1 0 0 0 1 1 0 0 0 0 0 0 1 1 3 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 (3, 5, W) 4 1 1 0 1 1 1 0 0 0 0 0 0 (2, 4, SE) (1, 5, SW) 5 1 1 0 0 0 0 0 0 0 0 0 0 (1, 4, E) 6 0 1 1 1 0 0 0 0 0 0 0 0 (1, 3, E) (2, 2, NE) 7 (1, 1, E) Move backward Program 3.16 maze: mark: 0 1 2 3 4 5 6 7 Stack 0 (5, 6, S) (5, 5, E) 1 0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 (5, 4, E) 2 1 0 0 0 1 1 0 0 1 0 0 1 0 0 (4, 3, SE) (3, 4, SW) 3 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 (3, 5, W) 4 1 1 0 1 1 1 0 0 0 0 0 0 (2, 4, SE) 1 (1, 5, SW) 5 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 (1, 4, E) 6 0 1 1 1 0 0 0 0 0 0 0 0 (1, 3, E) (2, 2, NE) 7 (1, 1, E) Result Analysis of Program 3.16 Space complexity: An extra 2D array mark is used: O(mp) Time complexity: The inner while-loop executes at most eight times for each direction. Each iteration takes O(1) time. Therefore, the inner loop totally takes O(1) time. The outer while loop executes until the stack is empty. If the number of zeros in the maze is z, at most z positions can be marked. Since z is bounded above by mp, the computing time is O(mp). Evaluation of Expression Expressions An expression is made up of operands, operators and delimiters. Example: A/B–C+D*E–A*C Operands: A, B, C, D, E (or constants). Operators: /, –, +, *. Delimiter: (, ). How to Evaluate an Expression in Right Order? Assign each operator a priority Priority of operators in C++ Priority Operator 1 Unary minus, ! High priority 2 *, /, % 3 +, - 4 <, <=, >=, > 5 ==, != 6 && 7 || Low priority How to evaluate A * B / C? Evaluate the expression from left to right. Use parentheses to define computation priority. Postfix Notation Each operator appears after its operands. The way of how compiler evaluate an expression. Example: Infix Notation Postfix Notation A+B AB+ A*B/C AB*C/ A/ B – C + D * E – A * C AB/C–DE*+AC*– 3.6.3 Infix to Postfix 1. Use parentheses to group operands according to the operator they use. 2. Change the position of operator. 3. Remove all the parentheses. Example: A/B –C + D*E – A*C Step 1. ( ( ( ( A / B ) – C ) + ( D * E )) – ( A * C ) ) Step 2. ( ( ( ( A B ) / C ) – ( D E ) *) + ( A C ) * ) – Step 3. AB / C – DE * + AC * – Exercises Convert the following infix expression into postfix notation. A*B/C A B) * / / B C) / ((A * B) C C) A/B–C+D*E–A*C Reasons to Convert Expressions to Postfix Notation Parentheses are eliminated. Example: Infix Notation Postfix Notation A * (B + C) ABC+* A/ B – (C + D) * E AB/CD+E*– Easier than infix evaluation. The priority of the operators is no longer relevant. Evaluate an Infix Expression Issues: How to convert infix notation to the postfix? How to evaluate an postfix expression? Clue: Using stack. Convert from Infix to Postfix Observation: The order of operands is unchanged Output operands immediately. A+B*C–DABC*+D– The order of A, B, C and D is unchanged. Stack operators until it is time to pass them to the output. Example 1 A + B * C Stack Next Stack Output Init. none empty none A empty A Output operand + + A Stack operator B + AB * +* AB ‘*’ has a priority higher than ‘+’. C +* ABC * empty ABC*+ Clear the stack + * Pop out stacked operators that has higher priority. Output: A B C * + Observation The stack is used for operators. The more upper the operator is, the higher its priority is. When a new operator p is coming, operators that has higher priority than p will be popped out first before p is pushed. Example 2 ( A + B ) * C Next Stack Output Stack Init. none empty none ( ( none ‘(‘ is pushed directly A ( A + (+ A No operator except ‘)’ can pop ‘(‘ B (+ AB ) empty empty AB+ ‘)’ pops out all operators until encountering the first ‘(‘; parentheses will not be output. * * AB+ + C empty AB+C ( * AB+C* Output: A B + C * Example 3 A * ( B + C ) * D Next Stack Output Init. none empty none A empty A Stack * * A ( *( A B *( AB + *(+ AB C *(+ ABC ) * ABC+ * * ABC+* The same priority. Pop out the old + one and push the new one. D * ABC+*D ( ABC+*D* * Output: A B C + * D * void InfixToPostfix (expression e) { Stack S; for (i=0; e[i] is not the end of string; i++) { Algorithm if (e[i] is an operand) output e[i]; else if (e[i] is ‘(’) S.Push(e[i]); else if (e[i] is not ‘)’) { while (S is not empty) { y = S.Pop(); if (y is not ‘(‘ and the priority of y >= the priority of e[i]) output y; else { S.Push(y); break; } } S.Push(e[i]); } else { //e[i] == ‘)’ while (S is not empty) { y = S.Pop(); if (y != ‘(‘) output y; else break; } } } Pop out all the elements in S and output; } Analysis of InfixToPostfix Suppose the input expression has length of n. Space complexity: O(n). The stack used to buffer operators at most requires O(n) elements. Time complexity: The function make only a left-to-right pass across the input. The time spent on each operand is O(1). The time spent on each operator is O(1). Each operator is stacked and unstacked at most once. Thus, the time complexity of InfixToPostfix() is O(n). Evaluate a Postfix Expression Strategy 1. Scan left to right. 2. Stack operands. 3. Evaluate operators using the top two operands on the stack and then push back the result. Program 3.18 A/B–C+D*E–A*C A B / C – D E * + A C * – Operations Postfix Notation The Stack is used for operands when evaluating the T1 = A / B T1 C – D E * + A C * – expression. T2 = T1 – C T2 D E * + A C * – If encountering T3 = D * E T2 T3 + A C * – operator, the top two are popped to E C T4 = T2 + T3 T4 A C * – perform computation. The result is pushed T5 = A * C T4 T5 – T3 D A C B T5 back. T4 T2 T1 A T6 T6 = T4 – T5 T6 Stack Program 3.18 Algorithm to evaluate a postfix expression void Eval (expression e) { Stack S; for (i=0; e[i] is not the end of string; i++) { if (e[i] is an operand) S.Push(e[i]); else //e[i] is an operator { t1 = S.Pop(); t2 = S.Pop(); Perform the operation of e[i] with t1 and t2 and store the result in X; S.Push(X); } } } Analysis of Eval() Suppose the input expression has length of n. Space complexity: O(n). The stack used to buffer operands at most requires O(n) elements. Time complexity: The function make only a left-to-right pass across the input. The time spent on each operand is O(1). The time spent on each operator to perform the operation is O(1). Thus, the time complexity of Eval() is O(n).