Stack is used to detect matching of expression brackets, binary tree is used to save the infix expression of the operation, and suffix expression is obtained through post-order traversal of the Expression Tree to obtain the expression value.
The detection pairing uses the stack save '(' symbol, when a ')' to exit the stack. If the stack is empty, an error occurs, the expression ends, and the stack is not empty.
3*5 + 2 construct a binary tree as follows
The four arithmetic operations have priority and combination relationships, which affect the construction process when constructing a binary tree. The operator with a higher priority has a deeper depth. In the subsequent sequential time, the operator is first traversed.
2 + 3*5 construct a binary tree as follows
In case of parentheses, the brackets are regarded as subarithmetic expressions and solved by recursion.
The following describes the algorithm used to replace an expression with an infix:
When the current symbol is the number of operations, check whether there is a root. If not, it is used as the root. Otherwise, it is used as the right child of the previous operator. If the root node does not have the right child, it is used as the right child, if you have a right Child, the right yuan of the right child is counted. If it is + or-, it is the last known operator. It is used as the root node, and the original tree is used as the left subtree. If it is * Or/, the priority is high, it is necessary to compare with the root node, how to change. If the root node is + or-, the operation should be performed first. Therefore, it is the root node of the right subtree and the original subtree is its left subtree. If it is of the same priority, the original is calculated first, and the current root node is used as the left subtree.
# Ifndef exceptions_h # define exceptions_h # include <exception> # include <iostream>/*** @ brief the outofboundary class out-of-bounds exception */class outofboundary: public STD :: exception {friend STD: ostream & operator <(STD: ostream & OS, const STD: exception & OBJ) {OS <obj. what (); Return OS;} public: outofboundary () Throw (): exception (){}~ Outofboundary () Throw () {} const char * What () const throw () {return "out of boundary! ";}};/*** @ Brief the badvalue class bad value exception */class badvalue: public STD: exception {friend STD: ostream & operator <(STD:: ostream & OS, const badvalue & OBJ) {OS <obj. what (); Return OS;} public: badvalue () Throw (): exception (){}~ Badvalue () Throw () {} const char * What () const throw () {return "bad value! ";}}; Class myexception: public STD: exception {public: myexception (const char * _ mes) Throw (): exception (), Info (_ mes ){}~ Myexception () Throw () {} const char * What () const throw () {return info. data ();} PRIVATE: STD: String Info;}; # endif # ifndef balance_hpp # define balance_hpp # include "linkstack. HPP "class balance {public: Enum elemtype {oparen, cparen, other, EOL}; balance (const char * Ex );~ Balance () {} bool balance (); Private: linkstack <char> _ stack; const char * _ ex; elemtype gettoken () ;}; inlinebalance :: balance (const char * Ex): _ ex (Ex) {} bool balance: Balance () {elemtype T = gettoken (); While (T! = EOL) {Switch (t) {Case oparen: _ stack. push ('); break; Case cparen: If (_ stack. isempty () {return false;} else {_ stack. pop ();} break; default: break;} t = gettoken ();} return _ stack. isempty (); \} balance: elemtype balance: gettoken () {elemtype re; while (* _ ex = '') ++ _ ex; if (* _ ex> = '0' & * _ ex <= '9 ') {While (* _ ex> = '0' & * _ ex <= '9') {++ _ ex;} return other ;} switch (* _ ex ++) {Case '(': Re = oparen; break; Case ')': Re = cparen; break; Case '\ 0': Re = EOL; break; default: Re = Other; break;} return re ;}# endif // balance_hpp # ifndef calculator_hpp # define calculator_hpp # include "balance. HPP "# include" exceptions. HPP "template <typename T> class calculator {public: /*** @ brief the elemtype Enum * number plus minus square brackets open Closed parentheses close end identifier */Enum elemtype {data, add, sub, mulit, Div, oparen, Cparen, EOL}; calculator (char * Ex );~ Calculator () {destroy (Root);} t result (); Private: struct node {elemtype; t data; node * LC, * RC; node (elemtype _ type, T _ data, node * _ lc = 0, node * _ rc = 0): type (_ type), data (_ data), LC (_ Lc ), RC (_ RC) {}}; node * Create (char * & Ex); elemtype gettoken (char * & Ex, T & value); void destroy (node * R ); t result (node * r); node * root;}; Template <typename T> calculator <t>: calculator (char * Ex) {balance B (Ex); If (! B. Balance () {Throw myexception ("() not match !!! ");} Root = create (Ex);} template <typename T> void calculator <t>: Destroy (node * r) {If (R! = NULL) {destroy (R-> Lc); destroy (R-> RC); Delete R ;}} template <typename T> typename calculator <t> :: node * calculator <t>: Create (char * & Ex) {node * P, * root = 0; elemtype retype; t value; while (* Ex) {retype = gettoken (ex, value); Switch (retype) {case data: Case oparen: If (retype = data) {P = new node (data, value );} else {/** solves this situation (4-2) * 5 tree structure: | ------ | _ | * | _ | ------ | ---------------> | ------ | (X) | \ | ------ | ----- | 4 | 2 | 4 | * | ------ | ----- | ------ | ----- | \ | ------ | 2 | 5 | ------ | ***/P = create (Ex ); node * q = new node (data, result (p); destroy (p); P = Q;} If (root = NULL) {root = P ;} else {If (root-> rc = NULL) {root-> rc = P;} else {root-> RC-> rc = P ;}} break; Case cparen: case EOL: Return root; Case Add: Case Sub: Root = new node (retype, 0, root); break; Case muak: Case Div: if (root-> type = data | root-> type = muyun | root-> type = div) {root = new node (retype, 0, root);} else {root-> rc = new node (retype, 0, root-> RC);} break; default: return NULL; break;} return root ;} template <typename T> typename calculator <t >:: elemtype calculator <t >:: gettoken (char * & Ex, T & Value) {char T; while (* Ex = '') ++ ex; If (* Ex> = '0' & * Ex <= '9') {value = 0; while (* Ex> = '0' & * Ex <= '9') {value = value * 10 + * ex-'0'; ++ ex ;} return data;} If (* Ex = '\ 0') return EOL; t = * Ex; ++ ex; Switch (t) {Case' + ': Return add; case '-': Return sub; Case '*': Return muyun; Case '/': Return div; Case '(': Return oparen; Case ')': Return cparen; default: Return EOL; }}template <typename T> T calculator <t >:: result () {return result (Root );} template <typename T> T calculator <t>: result (node * r) {elemtype T = r-> type; t T2, T3; If (t = data) {return r-> data;} t2 = result (R-> Lc); T3 = result (R-> RC); Switch (t) {Case Add: r-> DATA = T2 + T3; break; Case Sub: R-> DATA = T2-T3; break; Case muak: R-> DATA = T2 * T3; break; case Div: R-> DATA = T2/T3; break; default: break;} return r-> data;} # endif // calculator_hppint main () {try {calculator <int> ex ("(4-2) * (10 + (4 + 6)/2) + 2"); STD: cout <ex. result ();} catch (STD: exception & Ex) {STD: cout <ex. what () <STD: Endl;} return 0 ;}
Fix a bug and handle decimal points without checking for errors.
Template <typename T> typename calculator <t >:: elemtype calculator <t >:: gettoken (char * & Ex, T & Value) {char T; while (* Ex = '') ++ ex; If (* Ex> = '0' & * Ex <= '9') {value = 0; T = 0; t t2 = 1; bool F = false; // identify the decimal point while (* Ex> = '0' & * Ex <= '9 ') | * Ex = '. ') {If (* Ex = '. ') {f = true; ++ ex; continue;} If (! F) {value = value * 10 + * ex-'0';} else {T2 * = 0.1; t = T + (* ex-'0') * t2 ;} ++ ex;} value + = T; return data;} If (* Ex = '\ 0') return EOL; t = * Ex; ++ ex; switch (t) {Case '+': Return add; Case '-': Return sub; Case '*': Return mutries; Case '/': Return div; case '(': Return oparen; Case ')': Return cparen; default: Return EOL ;}}
Fix bugs
Balance: elemtype balance: gettoken () {elemtype re; while (* _ ex = '') ++ _ ex; // This code is not affected when it is commented out, however, function calls will be added, and the performance will be affected if (* _ ex> = '0' & * _ ex <= '9 ') {While (* _ ex> = '0' & * _ ex <= '9') | * _ ex = '. ') {++ _ ex;} return other;} switch (* _ ex ++) {Case' (': Re = oparen; break; case ')': re = cparen; break; Case '\ 0': Re = EOL; break; default: // handle all the situations that are not' ('') '\ 0, however, the function returns the string length + 1 Re = Other; break;} RET Urn re;} template <typename T> calculator <t>: calculator (char * Ex): Root (0), _ ex (Ex) {// balance B (Ex); // If (! B. Balance () {// throw myexception ("() not match !!! "); //} // An exception occurs in the constructor. As a result, the Destructor cannot be called. // root = create (Ex );} template <typename T> T calculator <t>: result () {balance B (_ ex); If (! B. Balance () {Throw myexception ("() not match !!! ");} Root = create (_ ex); return result (Root );}
_ Ex is the added data member