190 likes | 333 Views
DCO 20105 Data structures and algorithms. Lecture 12: Stack and Expression Evaluation Stack basic operations of a stack its implementation using a vector applications of stack Expression Evaluation Infix, Prefix, and Postfix expressions Implementation of evaluating a postfix expression
E N D
DCO20105 Data structures and algorithms • Lecture 12: Stack and Expression Evaluation • Stack • basic operations of a stack • its implementation using a vector • applications of stack • Expression Evaluation • Infix, Prefix, and Postfix expressions • Implementation of evaluating a postfix expression -- By Rossella Lau
C D B B B B A A A A Stack • Stack is an ordered list of items, ordered in the input sequence • Basically, items • are inserted and deleted at one end, called the top of the stack • are last in first out (LIFO) • An example: Add an item Add an item The original Take an item E C D
Operations of a stack • Basic: • push() – to add an item • pop() – to remove an item • Assistance: • size() – returns the number of items in a stack • empty() – to check if a stack is empty • top() – returns the first element of a stack; note that in a queue, it is called front()
Exercises • Ford: 7: 13,14; 8:11
Implementation of a stack using a vector // Stack.h template<class T> class Stack { private: vector<T> stack; public: void push(T const & item) {stack.push_back(item);} T & pop() {T t(top()); stack.pop_back(); return t;} size_t size() const { return stack.size();} bool empty() const { return stack.empty();} T const & top() const { return stack.back();} };
check check check main main main Applications of stack • Nested parentheses check • Expression evaluation • The underlying structure for recursion • Function calls (and its associated variables), e.g., : push init init push pop check … main
A stack application: nested parentheses check • Consider the parentheses in mathematical expressions 1. Equal number of right and left parentheses 2. Every right parenthesis is preceded by a matching parenthesis • Wrong expressions: ((A+B) violate condition 1 )A+B(-C violate condition 2 • Solution: nesting depth parenthesis count
Use of nesting depth and parenthesis count • Nesting depth: left parenthesis: open a scope right parenthesis: close a scope nesting depth at a particular point is the number of scopes that have been opened but not closed • Parenthesis count: at a particular point as the number of left parentheses minus the number of right parentheses if the count is not negative, it is the nesting depth • Check parentheses use by checking if parenthesis count: is greater than or equal to 0 at any point is equal to 0 at the end of the expression of course, checking should include the parenthesis type: {}, [],()
Use of a stack to check • For each left parenthesis, do a push • For each right parenthesis, do a pop and make sure the item popped is equal to the right parenthesis (same type) • If the stack is empty when doing a pop ERROR • If the stack is not empty when the expression ends ERROR • Examples of checking invalid expressions: [(A+B]) ((A+B) )A+B(-C ( ( ( ( ( Cannot pop ( ( [ [ !empty(s) Type mismatch
bool check(string expression){ valid = true stack<char> brackets while (expression not end){ read a symbol (symb) if symb is a left bracket brackets.push(symb) if symb is a right bracket{ if brackets.empty() valid=false if brackets.front() not match symb valid = false brackets.pop() } } if !brackets.empty() valid = false return valid} Algorithm to check pairs of parentheses {x+(y-[a+b])*c-(d+e)}/(h-(j-(k-[l-n]))) [ [ ( ( ( ( { { { { {x+(y-[ {…a+b]) {…*c-( {…d+e) [ [ ( ( { ( ( ( ( {…} …/(h-(j-(k-[ …l-n])))
Expression evaluation • An expression is a series of operators and operands • Operators: +, -, *, /, %, $ (exponentiation) • Operands: the values going to be operated Three representations of an expression: • Infix: The usual form, operator is between operands • Prefix: the operator is in front of the operand(s) • Postfix: the operand(s) is(are) in front of the operator
Infix A+B A+B-C (A+B)*(C-D) A$B*C-D+E/F/(G+H) ((A+B)*C-(D-E))$(F+G) A-B/(C*D$E) Prefix +AB -+ABC *+AB-CD +-*$ABCD//EF+GH $-*+ABC-DE+FG -A/B*C$DE Examples of Prefix Expressions
Infix A+B A+B-C (A+B)*(C-D) A$B*C-D+E/F/(G+H) ((A+B)*C-(D-E))$(F+G) A-B/(C*D$E) Postfix AB+ AB+C- AB+CD-* AB$C*D-EF/GH+/+ AB+C*DE--FG+$ ABCDE$*/- Examples of Postfix Expressions
/* for one digit operands and no space in the expression */ int eval(string const & expr) { Stack<int> operands; for (size_t i=0; i<expr.size();i++){ char c = expr[i]; if (isdigit(c)) //operand operands.push((double)(c-'0'); else { // operator int operand2=operands.pop(); int operand1=operands.pop(); operands.push(cal (c, operand1, operand2)); } } return operands.top(); } Evaluating a postfix expression • The advantage is no parentheses, i.e., less complication • Since the operator comes later, operands can be pushed to the stack first and once an operator is encountered, the operands are popped for the calculation • The algorithm (one digit operands) :
double eval(string const & expr) { Stack<double> operands; char c, number[MAX]; size_t i, j=0; double num; for (i=0; i<expr.size(); i++) { c = expr[i]; if (isdigit(c) || c=='.') number[j++]=c; else { // a token is parsed if (j) ...... // convert number to num operands.push(num); if (c != ' ') { // operand ...... // pop, cal, and push }} } return operands.top(); } ......//convert number to num number[j]='\0'; j=0; num = atof(number); ...... // pop, cal, and push double operand2 = operands.pop(); double operand1 = operands.pop(); operands.push(cal(c, operand1, operand2)); The algorithm for more than one digit
cal(char, double, double) double cal(char oper, double op1,double op2) { switch (oper) { // “operator” is a key word case '+': return op1 + op2; case '-': return op1 - op2; case '*': return op1 * op2; case '/': return op1 / op2; case '$': return pow(op1,op2); default: // should not happen exit(EXIT_FAILURE); } }
An example of postfix expression evaluation • 4 5 7 + * • scan 457: push(4), push(5), push(7) • scan +: op2=7, pop(), op1=5, pop(), push(op1+op2) • scan *: op2=12, pop(), op1=4, pop(), push(op1*op2) • expression end ==> return 48!
Summary • A stack is one of the most basic data structures in the study. • It only has one end for insert and delete. • An item in a stack is LIFO while it is FIFO in a queue • Stack is used in many hidden areas of computer systems • One popular important application is expression evaluation • An expression can be in three forms: infix, prefix, and postfix • It is common to evaluate an expression by using a postfix format
Reference • Ford: 7 • Example programs: evaluateIntExpression.cpp, evaluateDoubleExpression.cpp • STL online references • http://www.sgi.com/tech/stl • http://www.cppreference.com/ -- END --