1 / 56

CSCI2100B Stacks & Queues Jeffrey Yu@CUHK

CSCI2100B Stacks & Queues Jeffrey Yu@CUHK. Stack. Last-In-First-Out ( LIFO ): The last element being pushed onto a stack is the first element pop out. The efficiency comes with restricted accesses. 0, 1, 2, ..., n-1. 1. 2. 3. 1. 2. 3. 1. 2. 3.

yama
Download Presentation

CSCI2100B Stacks & Queues Jeffrey Yu@CUHK

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CSCI2100B Stacks & QueuesJeffrey Yu@CUHK

  2. Stack • Last-In-First-Out (LIFO): The last element being pushed onto a stack is the first element pop out. • The efficiency comes with restricted accesses. Stacks and Queues

  3. 0, 1, 2, ..., n-1 1 2 3 1 2 3 1 2 3 A Railroad Switching Network Stacks and Queues

  4. Stack ADT an-1 Top -> ….. a1 a0 • A stack is an ordered list in which insertions and deletions are made at one end called “top”. • Given a stack S = (a0, a1, ... , an-1) where a0 is the bottom element, ai is on top of ai-1. • Operations: • stack CreateS(int): create an empty stack with max elements. • Boolean IsEmpty(stack): if a stack is empty return TRUE. Otherwise, return FALSE. • Push(stack, element): add an element onto the top of a stack. • element Pop(stack): return and delete the topmost element on a stack. • element Top(stack): return the topmost element on a stack. Stacks and Queues

  5. mystack 6 size top -1 stack Stack Implementation (integers) typedefenum {FALSE = 0, TRUE = 1} Boolean; typedefstruct { intsize; int top; int*stack; } stack; stack *createS(int size){ stack *s; s = (stack*)malloc(sizeof(stack)); s->size = size; s->stack = (int*)malloc(size * sizeof(int)); s->top = -1; return s; } E.g. mystack = createS(6); Stacks and Queues

  6. Stack Implementation (integers) Boolean IsFull(stack *s){ if (s->top == s->size - 1) return TRUE; else return FALSE; } Boolean IsEmpty(stack *s){ if (s->top == -1) return TRUE; else return FALSE; } Stacks and Queues

  7. Stack Implementation (integers) void push(stack *s, int e){ if (! IsFull(s)) { s->top++; s->stack[s->top] = e; } } intpop(stack *s){ inti; if (! IsEmpty(s)) { i = s->stack[s->top]; s->top--; return i; } else { printf("error\n"); return -1; } } inttop(stack *s){ return s->stack[s->top];} Stacks and Queues

  8. Maze • How to solve it? • Need to try all the possible ways. • Need to remember the ways that have been tried. Stacks and Queues

  9. The MAZE Problem int maze[15][11]; intentryX= 0, entryY = 0, exitX = 14, exitY = 10; entry-> 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 N 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 | 0 0 0 1 1 0 1 1 0 1 1 1 1 1 1 W -+- E 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 | 0 0 0 1 0 0 0 0 1 1 1 1 1 0 1 S 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 -> exit Stacks and Queues

  10. A Data Structure • Need to define a data structure for remembering a corner in the maze • The location: x and y. • The direction we have tried in a predefined order: E SW N . • Let the data structure betypedefstruct{int x, y; char dir; } position; In short, we use <x, y, dir> to represent the structure. • This is the data structure to be pushed/popped in a stack. Stacks and Queues

  11. Maze: The Main Ideas • Remember the path from the entrance to the current position (Stack). • Move forward: Push! • To remember where we have visited. • Move backward: Pop! • To get where we were last time. • Remember the positions being tracked on the maze (Mark[][]). Stacks and Queues

  12. Pseudo Codes: get the maze's entrance. while(there is still a way to try) { get the current position and direction we are now; mark the current to remember we have visited; while(there is a possible move from the current) { identify the next position and direction to go; if (the next position is the exit) success and report the path; if (the next position is not wall and we have not visited before){ mark the next position to remember; remember it is as a step of the path; let the current (of the next move) be the next; }}} printf("No path found\n"); Stacks and Queues

  13. Pseudo Codes: initialize a stack to the maze's entrance. 1 while(stack is not empty) { • <x,y,dir> = pop from the top of stack; • mark[x][y] = 1; /* visited */ • while(there is a possible move from <x,y,dir>) { • <next_x, next_y> = coordinates of next move; • next_dir = direction of move; • if ((next_x == exitX) && (next_y == exitY)) • success and print the steps in the stack; • if (maze[next_x][next_y] == 0 && • mark[next_x][next_y] == 0){ • mark[next_x][next_y] = 1; • push <x,y,dir> to the stack; • x = next_x; y = next_y; dir = next_dir; • }}} • printf("No path found\n"); Stacks and Queues

  14. 0 0 0 1 0 1 1 0 0 0 0 0 00 0 1 0 1 1 0 0 0 0 0 000 1 0 1 1 0 0 0 0 0 000 1 0 1 1 0 0 0 0 0 (0,0) (0,0) (0,0) stack (1,0) Maze Problem: An Example (1) int maze[4][3]; intentryX = 0, entryY = 0, exitX = 3, exitY = 2; line-13 line-3 line-13 line-3 Red number means the current position. _ means visited as marked. Stacks and Queues

  15. 000 1 0 1 1 0 0 0 0 0 000 1 0 1 1 0 0 0 0 0 000 1 0 1 1 0 0 0 0 0 000 1 0 1 1 0 0 0 0 0 (0,0) (0,1) (0,0) (0,0) Maze Problem: An Example (2) line-13 line-13 line-3 line-9 Stacks and Queues

  16. 000 1 0 1 1 0 0000 000 1 0 1 1 0 0000 000 1 0 1 1 0 000 0 000 1 0 1 1 0 00 0 0 (2,2) (2,2) (1,2) (1,2) (1,2) (0,2) (0,2) (0,2) (0,2) (0,1) (0,1) (0,1) (0,1) (0,0) (0,0) (0,0) (0,0) Maze Problem: An Example (3) line-13 line-13 line-13 line-13 Stacks and Queues

  17. Calculator • How do we do calculation? • How does a machine do calculation? • Are they doing the things in the same way? • The algorithm? • The data structure to be used? Stacks and Queues

  18. Expressions: What We Learnt • An example: a / b - c + d * e - a * c • Four basic binary operators: +, -, *, /. • Operands: a, b, c, d, e. • Precedence of operators: The order in which the operators are performed. • (((a / b) - c) + (d * e)) - (a * c) • How do we evaluate operators with the same precedence? • a + b + c = (a + b) + c • The operators such as +, -, * and / are left-associative(from left to right). • Parentheses can be used to override precedence and expressions are always evaluated from the innermost parenthesized expression, • Example: a * (b + c) Stacks and Queues

  19. Operator Precedence used in C Highest • Note: here, we use a / b - c + d * e for easy representation (with space in between). • It should be a/b-c+d*e in fact (no space in between) Lowest Stacks and Queues

  20. Calculator • Reconsider examples: • a / b - c + d * e - a * c • (((a / b) - c) + (d * e)) - (a * c) • a + b + c = (a + b) + c • a * (b + c) • How do we design an algorithmto follow our rules? • What is the best way to do it? Stacks and Queues

  21. Calculator • The followings are for human to read. • a / b - c + d * e - a * c • (((a / b) - c) + (d * e)) - (a * c) • a + b + c = (a + b) + c • a * (b + c) • With the expression for human, it is hard to design a nice algorithm. • Why? • Consider some different expression formachine to work? Stacks and Queues

  22. Representations of Expressions • Consider the four binary operators +, -, * and /. • Infix Expressions: a binary operator is placed in-between its two operands. Disadvantages: need to use parentheses and precedence information when evaluate expressions. • Postfix Expressions: Each operator appears after its operands. Advantages: precedence has been considered when the postfix expression is generated. Stacks and Queues

  23. The Things to Be Done • Suppose a users give an infix expression. • Assume it is stored in an array of chars named expr[] • Convert the infix expression to a postfix expression. • Evaluate the postfix expression. • Also assume the postfix expression is stored in an array of chars named expr[] • Return the result to the user. Stacks and Queues

  24. An Overview char* expr; char infix[1000], postfix[1000]; int main() { int result; read expression by user into the infix array; expr = infix; /* expr can be used as an array of char */ postfix(); /* It accesses expr and stores the resulting postfix expression into the postfix array */ expr = postfix; result = eval(); printf(“%s = %d\n”, infix, result); return 0; } Stacks and Queues

  25. Some Preparations • The ASCII Code: • The char representation of the char ‘0’ is number 48. • The char representation of the char ‘8’ is number 56. • If we need an integer for ‘8’, we need to do ‘8’ – ‘0’ = 56 – 48 = 8. • Call by valuevscall by reference • Why do we need ‘call by reference’? • We want to return values in a flexible way. Stacks and Queues

  26. The American Standard Code for Information Interchange (ASCII) | 0 NUL| 1 SOH| 2 STX| 3 ETX| 4 EOT| 5 ENQ| 6 ACK| 7 BEL| | 8 BS | 9 HT | 10 NL | 11 VT | 12 NP | 13 CR | 14 SO | 15 SI | | 16 DLE| 17 DC1| 18 DC2| 19 DC3| 20 DC4| 21 NAK| 22 SYN| 23 ETB| | 24 CAN| 25 EM | 26 SUB| 27 ESC| 28 FS | 29 GS | 30 RS | 31 US | | 32 SP | 33 ! | 34 " | 35 # | 36 $ | 37 % | 38 & | 39 ' | | 40 ( | 41 ) | 42 * | 43 + | 44 , | 45 - | 46 . | 47 / | | 48 0 | 49 1 | 50 2 | 51 3 | 52 4 | 53 5 | 54 6 | 55 7 | | 56 8 | 57 9 | 58 : | 59 ; | 60 < | 61 = | 62 > | 63 ? | | 64 @ | 65 A | 66 B | 67 C | 68 D | 69 E | 70 F | 71 G | | 72 H | 73 I | 74 J | 75 K | 76 L | 77 M | 78 N | 79 O | | 80 P | 81 Q | 82 R | 83 S | 84 T | 85 U | 86 V | 87 W | | 88 X | 89 Y | 90 Z | 91 [ | 92 \ | 93 ] | 94 ^ | 95 _ | | 96 ` | 97 a | 98 b | 99 c |100 d |101 e |102 f |103 g | |104 h |105 i |106 j |107 k |108 l |109 m |110 n |111 o | |112 p |113 q |114 r |115 s |116 t |117 u |118 v |119 w | |120 x |121 y |122 z |123 { |124 | |125 } |126 ~ |127 DEL| Stacks and Queues

  27. Call by value • A procedure can return one thing, which can be any data structure, but just one. • Call-by-value • Suppose there is a procedureint add(inti, int j) {i = i+1, j=j+1; return i+j - 2;} • Consider the following codeinti, j, k;i = 10; j = 20; k = add(i, j); • What are the i value (10 or 11) and the j value (20 or 21)? Stacks and Queues

  28. Call by reference • In many cases, we want to get many things back but we do not want to define a data structure just for returning those things. • Call-by-reference • Suppose there is a procedureint add(int *i, int *j) {*i = *i+1, *j = *j+1; return *i+*j - 2;} • Consider the following codeinti, j, k;i = 10; j = 20; k = add(&i, &j); • What are the i value (10 or 11) and the j value (20 or 21)? Stacks and Queues

  29. Evaluation of Postfix Expressions Using Stack • Here, we only consider evaluation of expressions using the four binary operators +, -, * and /. • Procedure: • Create a new stack. • Scan the postfix expression from left-to-right. • If an operand is encountered, push it onto the stack. • If a binary operator is encountered, • pop two operands from the stack, • perform the operator, and • push the result onto the stack. • When the postfix expression has been scanned, the result is kept on the top of the stack. • Consider an infix expression: 6 / 2 - 3 + 4 * 2. Its postfix expression is 6 2 / 3 - 4 2 * +. How do we evaluate it? (Refer to Figure 3.14.) Stacks and Queues

  30. stack stack stack 2 3 4 6 3 0 2 8 6 8 0 0 0 3 4 To evaluate: 6 2 / 3 - 4 2 * + 6 2 / 3 - 4 2 * + 62/3 - 4 2 * + 62/3-42 * + 62 / 3 - 4 2 * + 62/3- 4 2 * + 62/3-42* + 62/ 3 - 4 2 * + 62/3-4 2 * + 62/3-42*+ Stacks and Queues

  31. Calculator: To Evaluate expr[]: an array of chars for a postfix expression. eval() { ... token = getToken(&symbol, &n); …} to evaluate a postfix expr. getToken(char *symbol, int *n) { … *symbol = expr[(*n)++]; switch (*symbol) { case '+' : returnplus; … } } • getToken returns three values: the current symbol, the position of the next symbol to read, and the meaning of the symbol -- symbol, n, and (plus, ….) Stacks and Queues

  32. Calculator: getToken expr[]: an array of chars for a postfix expression. eval() { ... token = getToken(&symbol, &n); …} to evaluate a postfix expr. getToken(char *symbol, int *n) { … *symbol = expr[(*n)++]; switch (*symbol) { case '+' : returnplus; … } } • An exampleexpr = “ab+”, n = 0; • 1st call getTokensymbol = ‘a’, n = 1, token = operand • 2nd call getTokensymbol = ‘b’, n = 2, token = operand • 3rd call getTokensymbol = ‘+’, n = 3,token = plus Stacks and Queues

  33. Reading Expressions typedefenum {lparen,rparen,plus,minus,times,divide,eos,operand } precedence; precedence getToken(char *symbol, int *n){ *symbol = expr[(*n)++]; /* expr: the expression string */ switch (*symbol) { case '+' : return plus; case '-' : return minus; case '/' : return divide; case '*' : return times; case '(' : return lparen; case ')' : return rparen; case '\0' : return eos; default : return operand; /* Assume single digit integers */ } } Stacks and Queues

  34. stack Evaluating Postfix Expressions inteval(void){ precedence token; char symbol; stack *s; int op1, op2; int n = 0; /* counter for the expression string expr*/ s = createS(100); token = getToken(&symbol, &n); while (token != eos) { if (token == operand) {op1 = symbol - '0'; push(s, op1); } else { op2 = pop(s); op1 = pop(s); switch(token) { case plus: push(s, op1 + op2); break; case minus: push(s, op1 - op2); break; case times: push(s, op1 * op2); break; case divide: push(s, op1 / op2); break; }} token = getToken(&symbol, &n); } return pop(s); /* return result */} /* char conversion to integer */ 6 2 / 3 - 4 2 * + Stacks and Queues

  35. Parenthesized Infix Expressions to Postfix Expressions • Infix expressions with one digit integers plus (, ), +, -, * and / • Example 1: Infix: a + b * cPostfix: a b c * + Infix: d - a + b * c / ePostfix: ? Stacks and Queues

  36. * * * + + * + * c ab*c+ Parenthesized Infix Expressions to Postfix Expressions • Example 2: a * b + c. Stacks and Queues

  37. Parenthesized Infix Expressions to Postfix Expressions • Example 3: a * (b + c) * d. • The left parenthesis is placed in the stack whenever it is found in the infix expression, but it is unstacked only when its matching right parenthesis is found. Stacks and Queues

  38. Parenthesized Infix Expressions to Postfix Expressions • Precedence: (Refer to Figure 3.12.) • The left parenthesis complicates matters because it behaves like a low-precedence operator when it is on the stack, and a high-precedence one when it is not. • Use two types of precedence • In-stack precedence (isp) • Incoming precedence (icp) Stacks and Queues

  39. Parenthesized Infix Expressions to Postfix Expressions • Precedence: (Refer to Figure 3.12.) • Implementation typedefenum {lparen, rparen, plus, minus, times, divide, eos, operand} precedence; intisp[] = {0, 19, 12, 12, 13, 13, 0}; inticp[] = {20, 19, 12, 12, 13, 13, 0}; int i; i = isp[plus]; Stacks and Queues

  40. Calculator: To Convert expr[]: an array of chars for an infix expression. postfix() { ... token = getToken(&symbol, &n); …} to convert an infix expr to a postfix expr. getToken(char *symbol, int *n) { … *symbol = expr[(*n)++]; switch (*symbol) { case '+' : returnplus; … } } • getToken returns three values: the current symbol, the position of the next symbol to read, and the meaning of the symbol -- symbol, n, and (plus, ….) Stacks and Queues

  41. Implementation void postfix() { char symbol; precedence token; int n = 0; stack *s; s = createS(100); push(s, eos); for (token = getToken(&symbol, &n); token != eos; token = getToken(&symbol,&n)) { if (token == operand) printSymbol(symbol); else if (token == rparen) { while (top(s) != lparen) printToken(pop(s)); pop(s); /* discard the left parenthesis */ } else { while(isp[top(s)] >= icp[token]) printToken(pop(s)); push(s, token); } } while ((token = pop(s)) != eos) printToken(token); } Stacks and Queues

  42. Queue • First-In-First-Out (FIFO): The first element being enqueuedinto a queue is the first element dequeued. • The efficiency comes with restricted accesses. Stacks and Queues

  43. Queue ADT • A queue is an ordered list in which all insertions (enqueues) are made at one end called “rear” and all deletions (dequeues) take place at the opposite end “front”. • Given a queue Q = (a0, a1, ..., an-1)where a0 is the front element, aiis behind ai-1. • Functions: • queue CreateQ(int): create an empty queue with max elements. • Boolean IsEmptyQ(queue): if the queue is empty return TRUE. Otherwise, return FALSE. • Boolean IsFullQ(queue): if the queue is full, return TRUE. Otherwise return FALSE. • queue enqueue(queue, element): add an element into the rear of the queue. • element dequeue(queue): return and delete the front element on a queue. Stacks and Queues

  44. q size 5 last -1 elements Implementation of Queue (1) typedefenum {FALSE = 0, TRUE = 1} Boolean; typedefstruct { int size; int last; int *elements; } queue; queue * createQ(int size) { queue *q; q = (queue*)malloc(sizeof(queue)); q->size = size; q->elements = (int*)malloc(size * sizeof(int)); q->last = -1; return q; } Stacks and Queues

  45. Implementation of Queue (2) Boolean IsFullQ(queue *q){ if (q->last == q->size - 1) return TRUE; else return FALSE; } Boolean IsEmptyQ(queue *q){ if (q->last == -1) return TRUE; else return FALSE; } void enqueue(queue *q, int e){ if (!IsFullQ(q)) { q->last++; q->elements[q->last] = e; } else printf("Error\n"); } intdequeue(queue *q){ inti, j; if (!IsEmptyQ(q)) { i = q->element[0]; for (j = 1; j <= q->last; j++) q->elements[j-1] = q->elements[j]; q->last--; return i; } else printf("Error\n");} Stacks and Queues

  46. Circular Queue • Use an array as a circular queue. • Why? To reduce the cost of moving elements. • If the “front” is equal to the “rear”, the circular queue is empty. typedefstruct { int size; int front; int rear; int *elements; } queue; Stacks and Queues

  47. q size 5 0 front rear 4 q elements 20 size 5 30 0 front 40 rear 3 q 50 elements q 20 size 5 size 5 30 -1 front -1 front 40 rear -1 rear 3 10 elements elements 20 30 40 To avoid moving elements Use a sequential queue typedefstruct { int size; int front; int rear; int *elements; } queue; Stacks and Queues

  48. [2] [3] [2] [3] 10 [1] [4] [1] [4] [0] [5] [0] [5] front = 0 rear = 0 front = 0 rear = 1 Circular Queues Enqueue 10 Stacks and Queues

  49. [2] [3] [2] [3] 20 30 10 10 [1] [4] [1] [4] [0] [5] [0] [5] front = 0 rear = 1 front = 0 rear = 3 More insertions Enqueue 20; Enqueue 30 Stacks and Queues

  50. [2] [3] [2] [3] 30 20 [1] [4] [1] [4] 10 [0] [5] [0] [5] front = 0 rear = 3 front = 1 rear = 3 Deletion (Dequeue) 30 20 Stacks and Queues

More Related