180 likes | 320 Views
Lecture #6a Topics. Abstract Data Type STACK. Three Implementations of class Stack: Living in a class List Object Living in an Array Living in a Linked List. Application: Building an Arithmetic Expression Evaluator Infix and Postfix Expressions
E N D
Lecture #6a Topics Abstract Data Type STACK Three Implementations of class Stack: Living in a class List Object Living in an Array Living in a Linked List Application: Building an Arithmetic Expression Evaluator Infix and Postfix Expressions Postfix Expression Evaluation Infix to Postfix Conversion A Generic class Stack Putting It All Together
ADT STACK Types ITEMTYPE,BOOLEAN Functions creations create: ---> STACK dissolve: STACK ---> transformations push: STACK,ITEMTYPE ---> STACK pop: STACK -/-> STACK observations top: STACK -/-> ITEMTYPE empty: STACK ---> BOOLEAN
Preconditions for all s,s’:STACK,item:ITEMTYPE pop(s)=s’ if not empty(s) top(s)=item if not empty(s) Axioms {Assumption: all preconditions have been met} for all s:STACK,item:ITEMTYPE empty(create())=true empty(push(s,item))=false pop(push(s,item))=s top(push(s,item))=item
5 7 -3 -3 7 -3 -3 7 7 7 7 s.topp s.topp s.topp 5 5 5 5 5 s.topp s.topp s.topp The Discipline of a Stack Structure: Last In – First Out (LIFO) Let topp indicate the top of the stack Stack s; s.push(5); s.push(7); s.push(-3); s.top( ); s.pop( );
} these 2 we’ll use implicitly Implementation of class Stack Living in a List Object Recall the Public Interface of class List (see Lecture 5, class List version 3) In particular we will employ the boldfaced methods to build class Stack class List { public: List(); ~List(); void insert(itemtype item,int pos); void remove(int pos); void overwrite(itemtype item,int pos); void retrieve(itemtype& item,int pos) const; int length() const; boolean empty() const; private: . . }; class List { public: List(); ~List(); void insert(itemtype item,int pos); void remove(int pos); void overwrite(itemtype item,int pos); void retrieve(itemtype& item,int pos) const; int length() const; boolean empty() const; private: . . }; the other 4 we’ll use explicitly
void insert(itemtype item,int pos); void remove(int pos); void retrieve(itemtype& item,int pos) const; boolean empty() const; #include “List.h” class Stack { public: void push(itemtype item) {L.insert(item,1);}; void pop() {L.remove(1);}; itemtype top() const; boolean empty() const {return L.empty();}; private: List L; }; itemtype Stack::top() const { itemtype item; L.retrieve(item,1); return item; }; As it stands the List class error handling will be used. If error handling specifically for class Stack is desired, put it in and adjust member functions pop( ) and top( ). E.g., what about error handling? void Stack::pop() { if (empty()) err(EMPTYERR); else L.remove(1); };
topp 0 1 2 3 n-1 . . . . 0 1 2 3 n-1 . . . . 0 1 2 3 n-1 . . . . 0 1 2 3 n-1 . . . . 0 1 2 3 n-1 . . . . 0 1 2 3 n-1 . . . . A A A A A A topp 23 topp topp 23 17 topp topp 23 17 -9 23 17 -9 23 17 -9 Implementation of class Stack Living in an Array Again let topp indicate the top of the stack Stack s; //topp is set to -1 s.push(23); //topp is incremented //A[topp] is set to 23 s.push(17); //topp is incremented //A[topp] is set to 17 s.push(-9); //topp is incremented //A[topp] is set to -9 The stack bottom is pinned to the left hand side of the array -- it could have been pinned to the right hand side just as well. cout<<s.top( ); //A[topp] is displayed //on the output device s.pop( ); //topp is decremented
note the friendship in this case Implementation of class Stack Living in a Linked List And class node: Some goodies: class node { friend class Stack; private: itemtype item; node* next; }; enum boolean {FALSE,TRUE}; typedef int itemtype; class Stack { public: Stack():topp(NULL) {}; ~Stack(); void push(itemtype item); void pop(); itemtype top() const; boolean empty() const {return topp==NULL;}; private: node* topp; enum stackerror {UNDERFLOW,EMPTY}; void err(stackerror e); }; //the destructor Stack::~Stack() { while (!empty()) pop(); };
Pushing an Item on the Stack topp NULL topp NULL num num p p p topp topp num NULL num NULL p Boundary Conditions: Given the Stack object shown: Can the code be used, as is, to push an item on an empty Stack? YES! node* p=new node; p->item=num; node* p=new node; p->item=num; p->next=topp; topp=p; p->next=topp; topp=p;
Popping an Item off the Stack topp NULL p topp topp topp NULL NULL NULL p p p Boundary Conditions: Given the Stack object shown: Can the code be used, as is, to pop the last item off a Stack? YES! node* p=topp; node* p=topp; topp=p->next; delete p; topp=p->next; delete p; Of course, an attempt to pop an empty Stack raises an exception.
Copying the Top Item in the Stack topp NULL Boundary Conditions: Given the Stack object shown: None! return topp->item; Of course, an attempt to copy the top of an empty Stack raises an exception.
Building an Arithmetic Expression Evaluator Infix and Postfix Expressions: Assume 1-digit integer operands and the binary operators + - * / only Infix Expression Properties: Usual precedence and associativity of operators Parentheses used to subvert precedence Postfix Expression Properties: Both operands of binary operators precede operator Parentheses no longer needed Infix Expression Equivalent Postfix Expression 3*4+5 34*5+ 3*(4+5)/2 345+*2/ (3+4)/(5-2) 34+52-/ 7-(2*3+5)*(8-4/2) 723*5+842/-*- 3-2+1 32-1+
Building an Arithmetic Expression Evaluator value of expression at top of stack Assume 1-digit integer operands, the binary operators + - * / only, and the string to be evaluated is properly formed Postfix Expression String Processing Rules for processing the postfix string: Starting from the left hand end, inspect each character of the string 1. if it’s an operand – push it on the stack 2. if it’s an operator – remove the top 2 operands from the stack, perform the indicated operation, and push the result on the stack An Example:3*(4+5)/2 345+*2/ 13 Remaining Postfix String int Stack (top) Rule Used 345+*2/ empty 45+*2/ 3 1 5+*2/ 3 4 1 +*2/ 3 4 5 1 *2/ 3 9 2 2/ 27 2 / 27 2 1 null 13 2
Building an Arithmetic Expression Evaluator Infix to Postfix Conversion Assume 1-digit integer operands, the binary operators + - * / only, and the string to be converted is properly formed Rules for converting the infix string: Starting from the left hand end, inspect each character of the string 1. if it’s an operand – append it to the postfix string 2. if it’s a ‘(‘ – push it on the stack 3. if it’s an operator – if the stack is empty, push it on the stack else pop operators of greater or equal precedence and append them to the postfix string, stopping when a ‘(‘ is reached, an operator of lower precedence is reached, or the stack is empty; then push the operator on the stack 4. if it’s a ‘)’ – pop operators off the stack, appending them to the postfix string, until a ‘(‘ is encountered and pop the ‘(‘ off the stack 5. when the end of the infix string is reached – pop any remaining operators off the stack and append them to the postfix string
Infix to Postfix Conversion (continued) An Example: 7-(2*3+5)*(8-4/2) 723*5+842/-*- Remaining Infix String char Stack Postfix String Rule Used 7-(2*3+5)*(8-4/2) empty null -(2*3+5)*(8-4/2) empty 7 1 (2*3+5)*(8-4/2) - 7 3 2*3+5)*(8-4/2) -( 7 2 *3+5)*(8-4/2) -( 72 1 3+5)*(8-4/2) -(* 72 3 +5)*(8-4/2) -(* 723 3 5)*(8-4/2) -(+ 723* 3 )*(8-4/2) -(+ 723*5 1 *(8-4/2) - 723*5+ 4 (8-4/2) -* 723*5+ 3 8-4/2) -*( 723*5+ 2 -4/2) -*( 723*5+8 1 4/2) -*(- 723*5+8 3 /2) -*(- 723*5+84 1 2) -*(-/ 723*5+84 3 ) -*(-/ 723*5+842 1 null empty 723*5+842/-*- 4&5
Building an Arithmetic Expression Evaluator Consider a class named Holder: A template version of class Holder: class Holder { public: void store(int item); int retrieve() const; private: int cell; }; template <class T> class Holder { public: void store(T item); T retrieve() const; private: T cell; }; Declaring a Holder object and storing a value in it: Declaring Holder objects and storing values in them: Holder h; h.store(19); Holder<int> h1; Holder<char> h2; h1.store(19); h2.store(‘A’); A Generic class Stack: A template class Note that a character stack is needed to convert an infix expression to postfix form and an integer stack is needed to evaluate a postfix expression. So it makes sense to introduce the idea of a template class and use a template class Stack when “Putting It All Together”. A class template is automatically expanded into a regular class declaration as needed by the compiler. More will be said about templates in a future Lecture.
Building an Arithmetic Expression Evaluator node Stack InfixToPostfix PostfixExpressionEvaluator InToEval Putting It All Together: Object Model Diagram
Building an Arithmetic Expression Evaluator Putting It All Together: File Inclusions Click on “.h” & “.cpp” files to view source code Stack.h InToPost.h PostEval.h InToPost.cpp PostEval.cpp InToEval.cpp Click on this “.exe” file to run the program (remember to enter a properly formed infix expression terminated by ‘#’) InToEval.exe