Date post: | 28-Dec-2015 |
Category: |
Documents |
Upload: | cory-hubbard |
View: | 223 times |
Download: | 0 times |
2 -1
Chapter 2
The stack
2 -2
Stack and QueueStack: Last-In-First-Out (LIFO) Last-Come-First-Serve (LCFS) only one endQueue: First-In-First-Out (FIFO) First-Come-First-Serve (FCFS) 2 ends one for entering one for leaving
F
E
D
C
B
A
top
Bottom of stackStack
2 -3
A motion picture of a stack
F
E
D
C
B
A
G
F
E
D
C
B
A
H
G
F
E
D
C
B
A
I
H
G
F
E
D
C
B
A
J
I
H
G
F
E
D
C
B
A
I
H
G
F
E
D
C
B
A
H
G
F
E
D
C
B
A
G
F
E
D
C
B
A
E
D
C
B
A
F
E
D
C
B
A
K
E
D
C
B
A
E
D
C
B
A
D
C
B
A
C
B
A
G
C
B
A
(a) (b) (c) (d) (e) (f) (g) (h) (i) (j) (k) (l) (m) (n) (o)
Push(S, G)Push(S, I)
Pop(S)Pop(S)
Push(S, K)
top
2 -4
Operations of a stackpush(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)
2 -5
Checking parentheses
7 - ( ( X * ( ( X + Y ) / ( J – 3 ) ) + Y ) / ( 4 - 2.5 ) )
( ( A + B )
) A + B (
**
**檢查方法 :
Check whether the parantheses are nested correctly.
2 -6
Checking various parentheses
{x + (y - [a+b]) * c – [(d+e)]} / (h-j)
**
檢查方法 :
.
**
Check whether one left parenthesis matches the corresponding right parenthesis
2 -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 */
2 -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”);
2 -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’;
2 -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;
2 -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]; };
2 -12
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 */
Different data types in a stack (2)
2 -13
Modulization (1) Individual functions are isolated into low-leve
l 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)
2 -14
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);
Modulization (2)
2 -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 */
2 -16
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 */
Push of a stack
2 -17
int stacktop(struct stack *ps) { if (empty(ps)){ printf(”%s”, ”stack underflow”); exit(1); } else return(ps->items[ps->top]); } /*end stacktop */
Pop of a stack
2 -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)
2 -19
Expression tree (1)
+
*A
B C
infix : A + (B*C)Prefix : + A * B CPostfix: A B C * +
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
2 -20
Expression tree (2)e.g. (A+B) * C infix (AB+) * C (AB+)C * AB+C * postfix
+
*
C
A B
infix : (A+B) * Cprefix : * + A B Cpostfix: A B + C *
2 -21
e.g. infix A$B*C-D+E/F/(G+H) /* $: exponentation, 次方 */
expression tree:+
+/
/-
*
$
D
C E F G H
A B
postfix :prefix :
**
Expression tree (3)
2 -22
precedence: (, ) > $ > *, / > +, -
left associative : A+B+C = (A+B)+C right associative: A$B$C = A$(B$C)
e.g. 6 2 3 + - 3 8 2 / + * 2 $ 3 +
infix form: ((6 - (2+3)) * (3 + 8/2)) $ 2 + 3 = 52
5 41 7
749
52
Evaluating a postfix expression
2 -23
symb opnd1 opnd2 value opndstk6 62 6, 23 6, 2, 3 + 2 3 5 6, 5- 6 5 1 13 6 5 1 1, 38 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 72 1 7 7 7, 2 $ 7 2 49 493 7 2 49 49, 3 + 49 3 52 52
Evaluation with a stack
2 -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));
**
2 -25
How to verify a postfix expression?
**方法一 :
方法二 :
2 -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);
2 -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]; };
2 -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 */
2 -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
2 -30
Conversion from infix to postfix
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+
2 -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+$
2 -32
Algorithm for conversion1) 遇 operand, 直接 output
2) 遇 operator (a) 若此 operator 之 precedence 比 top of stack 高 ==> 此 operator 放入 stack. (b) 否則 , 將所有比此 operator 之 precedence 還 高之 operator 全 pop 並 output, 再將比 operator 放入 stack.
3)
4)
5)
**
2 -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 *);
2 -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 */
2 -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 */
2 -36
evaluation algorithm 比 conversion algorithm 容易 , 因為 conversion 必須考慮各種 operator 之 precedence, 而 evaluation 則在看到一個 operator 時 , 即可計算 ( 沒有 precedence 問題 )
如何檢查是否為 valid infix expression? **
Evaluation and conversion
2 -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 };
2 -38
Stack implementation with templates
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; };
2 -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; };
2 -40
// The tasks of this function were formerly// performed by popandtesttemplate <class T> T Stack<T>::pop(int & und){ T p;
if (empty()){ und = 1; return p; } und = 0; p = nodes[top--]; return p;};
2 -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
2 -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
2 -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); }
2 -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 */
2 -45
long double oper(int symb,long double op1,long double op2) // body of oper goes here
long double 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 */
2 -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; }