1 / 46

Chapter 2

Chapter 2. The stack. Stack and Queue. Stack : Last-In-First-Out ( LIFO ) Last-Come-First-Serve (LCFS) only one end Queue : First-In-First-Out ( FIFO ) First-Come-First-Serve (FCFS) 2 ends one for entering one for leaving.

Download Presentation

Chapter 2

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. Chapter 2 The stack

  2. Stack and Queue Stack: Last-In-First-Out (LIFO) Last-Come-First-Serve (LCFS) only one end Queue: First-In-First-Out (FIFO) First-Come-First-Serve (FCFS) 2 ends one for entering one for leaving top Bottom of stack Stack

  3. A motion picture of a stack Push(S, K) Push(S, G) Pop(S) Push(S, I) Pop(S) top (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) (k) (l) (m) (n) (o)

  4. Operations of a stack push(S, i): add item i into the top of stack S. i = pop(S): remove the top of stack S and assign its value to i. empty(S) : check whether a stack S is empty or not. underflow: pop or access an item from an empty stack. i=stacktop(S): return the top of stack S. can be written as: i = pop(S) Push(S, i)

  5. Checking parentheses • Check whether the parantheses are nested correctly. 7 - ( ( X * ( ( X + Y ) / ( J – 3 ) ) + Y ) / ( 4 - 2.5 ) ) ** ( ( A + B ) ) A + B ( 檢查方法: **

  6. Checking various parentheses . • Check whether one left parenthesis matches the corresponding right parenthesis {x + (y - [a+b]) * c – [(d+e)]} / (h-j) ** 檢查方法: **

  7. Pseudo code for parenthesis (1) vaild = true;/* assume the string is valid */ s = the empty stack; while (we have not read the entire string) { read the next symbol (symb) of the string; if (symb == ’(’ || symb == ’[’ || symb == ’{’)// 左括號 push(s, symb); if (symb == ’)’ || symb == ’]’ || symb == ’}’)// 右括號 if (empty(s)) valid = false; else{ i = pop(s); if (i is not the matching opener of symb) valid = false;// 括號形狀不同 } /* end else */ } /* end while */

  8. Pseudo code for parenthesis (2) if (!empty(s))// 最後須為空的 valid = false; if (valid) printf(”%s”, ”the string is valid”); else printf(”%s”, ”the string is invalid”);

  9. Representing a stack as an abstract data type abstract typedef <<eltype>> STACK (eltype); abstract empty(s) STACK(eltype) s; postcondition empty == (len(s) == 0); abstract eltype pop(s) STACK(eltype) s,s’; precondition empty(s) == FALSE; postcondition pop == first(s); s’==s; s == sub(s’, 1, len(s’)-1); abstract push(s, elt) STACK(eltype) s,s’; eltype elt; postcondition s’=s; s == <elt> + s’;

  10. Representing stacks with C • A stack is an order collection of items. #define STACKSIZE 100 struct stack { int top; int items[STACKSIZE]; }; struct stack s;

  11. Different data types in a stack (1) #define STACKSIZE 100 #define INT 1 #define FLOAT 2 #define STRING 3 struct stackelement { int etype; /* etype equals INT, FLOAT, or STRING */ /* depending on the type of the */ /* corresponding element */ union{ int ival; float fval; char *pval; /* pointer to a string */ } element; }; struct stack { int top; struct stacklement items[STACKSIZE]; };

  12. Different data types in a stack (2) struct stack s; struct stackelement se; ... se = s.items[s.top]; switch (se.etype) { case INT : printf(”%d \n”, se.element.ival); case FLOAT : printf(”%f \n”, se.element.fval); case STRING: printf(”%s \n”, se.element.pval); } /* end switch */

  13. Individual functions are isolated into low-level modules. • int empty(struct stack *ps) • { • if (ps->top == -1) • return(TRUE); • else • return(FALSE); • } /* empty */ • How to call empty() in the calling program? • if (empty (&s)) • /* stack is empty */ • else • /* stack is not empty */ return (ps->top == -1) Modulization (1)

  14. Modulization (2) • int pop(struct stack *ps) • { • if (empty(ps)){ • printf(”%s”, “stack underflow”); • exit(1); • } /* end if */ • return(ps->item[ps->top--]); • } /* end pop */ • How to call pop() in the calling program? • x = pop (&s);

  15. Modulization (3) void popandtest(struct stack *ps, int *px, int *pund) • { // pop及測試是否underflow • if (empty(ps)){ • *pund = TRUE; • return; • } /* end if */ • *pund = FALSE; • *px = ps->items[ps->top--]; • return; • } /* end popandtest */ • calling program: • popandtest(&s, &x, &und); • if (und) • /* take corrective action */ • else • /* use value of x */

  16. Push of a stack void push(struct stack *ps, int x){ ps->items[++(ps->top)] = x; return; } /* end push */ • overflow: put an item onto a full stack void push(struct stack *ps, int x) { if (ps->top == STACKSIZE-1){ printf(”%s”, ”stack overflow”); exit(1); } else ps->items[++(ps->top)] = x; return; } /* end push */

  17. Pop of a stack int stacktop(struct stack *ps) { if (empty(ps)){ printf(”%s”, ”stack underflow”); exit(1); } else return(ps->items[ps->top]); } /*end stacktop */

  18. Infix, postfix, prefix expressions • infix A+B /* A, B: operands, +: operator */ • postfix AB+ • (reverse Polish notation) • prefix +AB • (Polish notation) • Conversion from infix to postfix: • e.g. A + (B*C) infix(inorder) • A + (BC*) • A(BC*)+ • ABC * + postfix(postorder)

  19. inorder traversal: 1. left subtree 2. root 3. right subtree preorder traversal: 1. root 2. left subtree 3. right subtree postorder traversal: 1. left subtree 2. right subtree 3. root Expression tree (1) + infix : A + (B*C) Prefix : + A * B C Postfix: A B C * + * A B C

  20. Expression tree (2) e.g. (A+B) * C infix (AB+) * C (AB+)C * AB+C * postfix * infix : (A+B) * C prefix : * + A B C postfix: A B + C * + C A B

  21. Expression tree (3) e.g. infix A$B*C-D+E/F/(G+H) /* $: exponentation, 次方 */ expression tree: + - / * / + D C E F G H $ A B postfix :prefix : **

  22. precedence: (, ) > $ > *, / > +, - • left associative : A+B+C = (A+B)+C • right associative: A$B$C = A$(B$C) Evaluating a postfix expression e.g. 6 2 3 + - 3 8 2 / + * 2 $ 3 + infix form: ((6 - (2+3)) * (3 + 8/2)) $ 2 + 3 = 52 5 4 1 7 7 49 52

  23. Evaluation with a stack symb opnd1 opnd2 value opndstk 6 6 2 6, 2 3 6, 2, 3 + 2 3 5 6, 5 - 6 5 1 1 3 6 5 1 1, 3 8 6 5 1 1, 3, 8 2 6 5 1 1, 3, 8, 2 / 8 2 4 1, 3, 4 + 3 4 7 1, 7 * 1 7 7 7 2 1 7 7 7, 2 $ 7 2 49 49 3 7 2 49 49, 3 + 49 3 52 52

  24. Algorithm (演算法) ** opndstk = the empty stack; /* scan the input string reading one */ /* element at a time into symb */ while (not end of input){ symb = next input character; if (symb is an operand) push(opndstk, symb); else{ /* symb is an operator */ opnd2 = pop(opndstk); opnd1 = pop(opndstk); value = result of applying symb to opnd1 and opnd2; push (opndstk, value); } /* end else */ } /* end while */ return(pop(opndstk));

  25. How to verify a postfix expression? ** 方法一: 方法二:

  26. Evaluating a postfix expression with C #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAXCOLS 80 #define TRUE 1 #define FALSE 0 double eval(char[]); double pop(struct stack *); void push(struct stack *,double); int empty(struct stack *); int isdigit(char); double oper(int, double, double);

  27. void main() { char expr[MAXCOLS]; int position = 0; while ((expr[position++] = getchar()) != ’\n’); expr[--position] = ’\0’; printf (”%s%s”, ”the original postfix expression is”, expr); printf(”\n%f”, eval(expr)); } /* end main */ struct stack{ int top; double items[MAXCOLS]; };

  28. double eval(char expr[]) { int c, position; double opnd1, opnd2, value; struct stack opndstk; opndstk.top = -1; for (position = 0; (c = expr[position]) != ’\0’; position++) if (isdigit(c)) /* operand– convert the character representation */ /* of the digit into double and push it onto */ /* the stack */ push(&opndstk, (double) (c - ’0’); else{ /* operator */ opnd2 = pop(&opndstk); opnd1 = pop(&opndstk); value = oper(c, opnd1, opnd2); push(&opndstk, value); } /*end else */ return(pop(&opndstk)); } /*end eval */

  29. int isdigit(char symb) • { • return(symb >= ’0’ && symb <= ’9’); • } • double oper(int symb, double op1, double op2) • { • switch(symb){ • case ’+’ : return (op1 + op2); • case ’-’ : return (op1 – op2); • case ’*’ : return (op1 * op2); • case ’/’ : return (op1 / op2); • case ’$’ : return (pow(op1, op2)); // 計算次方 • default : printf(”%s”, ”illegal operation”); • exit(1); • } /* end switch */ • } /* end oper */ • 此程式無法處理 2-digit number 及 minus sign

  30. e.g. A+B*C ABC*+ symb postfix string opstk 1 A A 2 + A + 3 B AB + 4 * AB + * 5 C ABC + * 6 ABC * + 7 ABC * + e.g. A*B+C AB*C+ Conversion from infix to postfix

  31. e.g. ((A-(B+C))*D)$(E+F) ABC+-D*EF+$ symb postfix string opstk ( ( ( (( A A (( - A ((- ( A ((-( B AB ((-( + AB ((-(+ C ABC ((-(+ ) ABC+ ((- ) ABC+- ( * ABC+- (* D ABC+-D (* ) ABC+-D* $ ABC+-D* $ ( ABC+-D* $( E ABC+-D*E $( + ABC+-D*E $(+ F ABC+-D*EF $(+ ) ABC+-D*F+ $ ABC+-D*EF+$

  32. Algorithm for conversion 1)遇 operand, 直接 output 2)遇 operator (a) 若此 operator 之 precedence 比 top of stack 高 ==> 此 operator 放入 stack. (b) 否則, 將所有比此 operator 之precedence 還 高之 operator 全 pop 並 output, 再將比 operator 放入 stack. ** 3) 4) 5)

  33. C program for conversion #include <stdio.h> #include <stdlib.h> #define MAXCOLS 80 #define TRUE 1 #define FALSE 0 void postfix(char *, char *); int isoperand(char); void popandtest(struct stack *, char *, int *); int prcd(char, char); void push(struct stack *, char); char pop(struct stack *);

  34. struct stack { int top; char items[MAXCOLS]; } postfix(char infix[], char postr[]) { int position, und; int outpos = 0; char topsymb = ’+’; char symb; struct stack opstk; opstk.top = -1; /* the empty stack */ for (position = 0; (symb = infix[position])!= ’\0’; position++) if (isoperand(symb)) postr[outpos++] = symb; else{ popandtest(&opstk, &topsymb, &und); while (!und && prcd(topsymb, symb)){ postr[outpos++] = topsymb; popandtest(&opsatk, &topsymb, &und); } /* end while */

  35. if (!und) push(&opstk, topsymb); if (und || (symb != ’)’) ) push(&opstk, symb); else topsymb = pop(&opstk); } /* end else */ while (!empty(&opstk)) postr[outpos++] = pop(&opstk); postr[outpos] = ’\0’; return; } /* end postfix */

  36. Evaluation and conversion evaluation algorithm 比 conversion algorithm容易, 因為conversion 必須考慮各種operator 之precedence, 而 evaluation 則在看到一個operator時, 即可計算 (沒有 precedence 問題) 如何檢查是否為 valid infix expression? **

  37. Stacks in C++ using template template <class T> // T is a parameter // T is of ordinal type // undetermined type class Stack { private: int top; T *nodes; public: Stack(); // default constructor int empty(void); void push(T &); T pop(void); T pop(int &);// example of overloading pop // to handle the functions // of popandtest default ~Stack(); // destructor };

  38. Constructor for stack template <class T> Stack<T>::Stack() { top = -1; nodes = new T[STACKSIZE]; }; • Destructor for stack template <class T> Stack<T>::~Stack() { delete nodes; }; Stack implementation with templates

  39. template <class T> int Stack<T>::empty (void) { return top < 0; }; template <class T> void Stack<T>::push(T & j) { if (top == STACKSIZE){ cout << “Stack overflow” << endl; return; } nodes[++top] = j; }; template <class T> T Stack<T>::pop(void) { T p; if (empty()){ cout << “Stack underflow” << endl; return p; } p = nodes[top--]; return p; };

  40. // The tasks of this function were formerly // performedby popandtest template <class T> T Stack<T>::pop(int & und) { T p; if (empty()){ und = 1; return p; } und = 0; p = nodes[top--]; return p; };

  41. To make use of the stack, include all of the prototype definitions • // stackt.h • #ifndef STACKT_H • #define STACKT_H • #include <stdio.h> • #include <stdlib.h> • #include <alloc.h> • #include <mem.h> • #include <iostream.h> • #define STACKSIZE 100 • #endif

  42. Evaluating infix expression with stack void postfix(char *infix, char *postr); int prcd(char op1, char op2); int isoperand(char op); int isoperator(char op); long double eval(char *postr); long double oper(int symb, long double op1, long double op2); int prcd(char op1, char op2) // body of prcd goes here int isoperator(char op) // body of isoperator goes here int isoperand(char op) // body of isoperand goes here

  43. void postfix(char *infix, char *postr) { int position, und; int outpos = 0; char topsymb = ’+’; char symb; Stack<char> opstk; for (position = 0; (symb = infix[position])!= ’\0’; position++) { if (isoperand(symb)) postr[outpos++] = symb; else{ topsymb = opstk.pop(und); while (!und && prcd(topsymb, symb)){ postr[outpos++] = topsymb; topsymb = opstk.pop(und); }

  44. if (!und) opstk.push(topsymb); if (und || (symb != ’)’) ) opstk.push(symb); else topsymb = opstk.pop(); } } /* end for */ while (!opstk.empty()) postr[outpos++] = opstk.pop(); postr[outpos] = ’\0’; } /* end postfix */

  45. longdouble oper(int symb,longdouble op1,longdouble op2) // body of oper goes here longdouble eval(char *postr) { int c, position; long double opnd1, opnd2, value; Stack<long double> opndstk; for (position = 0; (c = postr[position]) != ’\0’; position++) if (isoperand(c)) opndstk.push((float) (c-’0’)); else{ opnd2 = opndstk.pop(); opnd1 = opndstk.pop(); value = oper(c, opnd1, opnd2); opndstk.push(value); } return (opndstk.pop()); } /* end eval */

  46. void main(void) { char in[250], post[250]; long double res; cin >> in; cout << in << endl; postfix(in, post); res = eval(post); cout << res << endl; }

More Related