首页 > 代码库 > 表达式求值(二叉树方法/C++语言描述)(四)

表达式求值(二叉树方法/C++语言描述)(四)

代码清单

  1 // binarytree.h
  2 #ifndef BINARYTREE_H
  3 #define BINARYTREE_H
  4 
  5 template <typename T> class BinaryTree;
  6 
  7 template <typename T>
  8 class BinaryTreeNode
  9 {
 10 public:
 11     friend class BinaryTree<T>;
 12     friend class Calculator;
 13     T _data;
 14 
 15 private:
 16     BinaryTreeNode<T> * _leftChild;
 17     BinaryTreeNode<T> * _rightChild;
 18 };
 19 
 20 template <typename T>
 21 class BinaryTree
 22 {
 23 public:
 24     BinaryTree()
 25     {
 26         _root = nullptr;
 27     }
 28 
 29     ~BinaryTree()
 30     {
 31         destory();
 32     }
 33 
 34     void preOrder()
 35     {
 36         preOrder(_root);
 37     }
 38 
 39     void inOrder()
 40     {
 41         inOrder(_root);
 42     }
 43 
 44     void postOrder()
 45     {
 46         postOrder(_root);
 47     }
 48 
 49 protected:
 50     BinaryTreeNode<T> * _root;
 51 
 52     void destory()
 53     {
 54         if (_root)
 55         {
 56             destory(_root);
 57             delete _root;
 58         }
 59     }
 60 
 61     void destory(BinaryTreeNode<T> * node)
 62     {
 63         if (node)
 64         {
 65             destory(node->_leftChild);
 66             destory(node->_rightChild);
 67             // visit binary tree data
 68             if (node->_leftChild)
 69             {
 70                 delete node->_leftChild;
 71             }
 72             if (node->_rightChild)
 73             {
 74                 delete node->_rightChild;
 75             }
 76         }
 77     }
 78 
 79     virtual void preOrder(BinaryTreeNode<T> * node)
 80     {
 81         if (node)
 82         {
 83             // visit binary tree data
 84             preOrder(node->_leftChild);
 85             preOrder(node->_rightChild);
 86         }
 87     }
 88 
 89     virtual void inOrder(BinaryTreeNode<T> * node)
 90     {
 91         if (node)
 92         {
 93             inOrder(node->_leftChild);
 94             // visit binary tree data
 95             inOrder(node->_rightChild);
 96         }
 97     }
 98 
 99     virtual void postOrder(BinaryTreeNode<T> * node)
100     {
101         if (node)
102         {
103             postOrder(node->_leftChild);
104             postOrder(node->_rightChild);
105             // visit binary tree data
106         }
107     }
108 };
109 
110 #endif // BINARYTREE_H
111 
112 // calculator.h
113 #ifndef CALCULATOR_H
114 #define CALCULATOR_H
115 
116 #include <cassert>
117 #include <string>
118 #include <stack>
119 #include <iostream>
120 #include "binarytree.h"
121 
122 using namespace std;
123 
124 typedef enum
125 {
126     BEGIN,
127     NUMBER,
128     OPERATOR,
129     LEFT_BRAC,
130     RIGHT_BRAC
131 } TokenType;
132 
133 class Token
134 {
135 public:
136     TokenType _type;
137     union
138     {
139         char op;
140         double num;
141     } _data;
142 };
143 
144 class Calculator : public BinaryTree<Token>
145 {
146 public:
147     void parseExpression(string expression) throw(string);
148     double calculate();
149 
150 private:
151     stack<char> _stkOperators;
152     stack<BinaryTreeNode<Token> *> _stkNodes;
153     stack<double> _stkNumbers;
154 
155     static int priority(char op);
156     static double calculate(double d1, char op, double d2) throw(string);
157 
158     void postOrder(BinaryTreeNode<Token> * node);
159     void calculateStack() throw(string);
160     void dealWithNumber(char *&pToken) throw(string);
161     void dealWithOperator(char *&pToken) throw(string);
162     void dealWithLeftBrac(char *&pToken) throw(string);
163     void dealWithRightBrac(char *&pToken) throw(string);
164 };
165 
166 #endif // CALCULATOR_H
167 
168 // calculator.cpp
169 #include "calculator.h"
170 
171 int Calculator::priority(char op)
172 {
173     assert(op == + || op == - || op == * || op == / || op == ();
174 
175     if (op == + || op == -)
176     {
177         return 1;
178     }
179     else if (op == * || op == /)
180     {
181         return 2;
182     }
183     else
184     {
185         return 0;
186     }
187 }
188 
189 double Calculator::calculate(double d1, char op, double d2) throw(string)
190 {
191     assert(op == + || op == - || op == * || op ==/);
192 
193     cout << d1 << op << d2 << endl;
194 
195     if (op == +)
196     {
197         return d1 + d2;
198     }
199     else if (op == -)
200     {
201         return d1 - d2;
202     }
203     else if (op == *)
204     {
205         return d1 * d2;
206     }
207     else
208     {
209         if (!d2)
210         {
211             throw string("divided by 0");
212         }
213         return d1 / d2;
214     }
215 }
216 
217 void Calculator::calculateStack() throw(string)
218 {
219     BinaryTreeNode<Token> * node = new BinaryTreeNode<Token>();
220     assert(node);
221     node->_data._type = OPERATOR;
222     node->_data._data.op = _stkOperators.top();
223     _stkOperators.pop();
224     assert(!_stkNodes.empty());
225     node->_rightChild = _stkNodes.top();
226     _stkNodes.pop();
227     assert(!_stkNodes.empty());
228     node->_leftChild = _stkNodes.top();
229     _stkNodes.pop();
230     _stkNodes.push(node);
231 }
232 
233 void Calculator::parseExpression(string expression) throw(string)
234 {
235     destory();
236     while (!_stkNodes.empty())
237     {
238         _stkNodes.pop();
239     }
240     while (!_stkOperators.empty())
241     {
242         _stkOperators.pop();
243     }
244     TokenType lastToken = BEGIN;
245 
246     char * pToken = &expression[0];
247     while (*pToken)
248     {
249         switch (lastToken)
250         {
251         case BEGIN:
252             if (*pToken == ()
253             {
254                 // an expression begin with a left bracket
255                 dealWithLeftBrac(pToken);;
256                 lastToken = LEFT_BRAC;
257             }
258             else
259             {
260                 // or a number
261                 dealWithNumber(pToken);
262                 lastToken = NUMBER;
263             }
264             break;
265         case NUMBER:
266             // after a number
267             if (*pToken == ))
268             {
269                 // it may be a right bracket
270                 dealWithRightBrac(pToken);
271                 lastToken = RIGHT_BRAC;
272             }
273             else
274             {
275                 // it may be an operator
276                 dealWithOperator(pToken);
277                 lastToken = OPERATOR;
278             }
279             break;
280         case OPERATOR:
281         case LEFT_BRAC:
282             // after an operator or a left bracket
283             if (*pToken == ()
284             {
285                 // it may be a left bracket
286                 dealWithLeftBrac(pToken);
287                 lastToken = LEFT_BRAC;
288             }
289             else
290             {
291                 // it may be a number
292                 dealWithNumber(pToken);
293                 lastToken = NUMBER;
294             }
295             break;
296         case RIGHT_BRAC:
297             // after a right bracket
298             if (*pToken == ))
299             {
300                 // it may be another right bracket
301                 dealWithRightBrac(pToken);
302                 lastToken = RIGHT_BRAC;
303             }
304             else
305             {
306                 // it may be an perator
307                 dealWithOperator(pToken);
308                 lastToken = OPERATOR;
309             }
310             break;
311         }
312     }
313 
314     while (!_stkOperators.empty())
315     {
316         if (_stkOperators.top() == ()
317         {
318             throw string("bad token ‘(‘");
319         }
320         calculateStack();
321     }
322 
323     assert(!_stkNodes.empty());
324     _root = _stkNodes.top();
325 }
326 
327 void Calculator::postOrder(BinaryTreeNode<Token> *node)
328 {
329     if (node)
330     {
331         postOrder(node->_leftChild);
332         postOrder(node->_rightChild);
333         // visit binary tree data
334         if (node->_data._type == NUMBER)
335         {
336             _stkNumbers.push(node->_data._data.num);
337         }
338         else
339         {
340             assert(!_stkNumbers.empty());
341             double d2 = _stkNumbers.top();
342             _stkNumbers.pop();
343             assert(!_stkNumbers.empty());
344             double d1 = _stkNumbers.top();
345             _stkNumbers.pop();
346             char op = node->_data._data.op;
347             _stkNumbers.push(calculate(d1, op, d2));
348         }
349     }
350 }
351 
352 double Calculator::calculate()
353 {
354     while (!_stkNumbers.empty())
355     {
356         _stkNumbers.pop();
357     }
358 
359     BinaryTree::postOrder();
360 
361     assert(!_stkNumbers.empty());
362     return _stkNumbers.top();
363 }
364 
365 void Calculator::dealWithNumber(char *&pToken) throw(string)
366 {
367     if (!isdigit(*pToken) && *pToken != -)
368     {
369         throw string("bad token ‘") + *pToken + "";
370     }
371 
372     BinaryTreeNode<Token> * node = new BinaryTreeNode<Token>();
373     assert(node);
374     node->_data._type = NUMBER;
375     node->_data._data.num = strtod(pToken, &pToken);
376     node->_leftChild = node->_rightChild = nullptr;
377     _stkNodes.push(node);
378 }
379 
380 void Calculator::dealWithOperator(char *&pToken) throw(string)
381 {
382     if (*pToken != + && *pToken != - && *pToken != * && *pToken != /)
383     {
384         throw string("bad token ‘") + *pToken + "";
385     }
386 
387     if (!_stkOperators.empty()
388             && priority(_stkOperators.top()) >= priority(*pToken))
389     {
390         calculateStack();
391     }
392     _stkOperators.push(*pToken++);
393 }
394 
395 void Calculator::dealWithLeftBrac(char *&pToken) throw(string)
396 {
397     if (*pToken != ()
398     {
399         throw string("bad token ‘") + *pToken + "";
400     }
401 
402     _stkOperators.push(*pToken++);
403 }
404 
405 void Calculator::dealWithRightBrac(char *&pToken) throw(string)
406 {
407     if (*pToken != ))
408     {
409         throw string("bad token ‘") + *pToken + "";
410     }
411 
412     while (!_stkOperators.empty() && _stkOperators.top() != ()
413     {
414         calculateStack();
415         if (_stkOperators.empty())
416         {
417             throw string("bad token ‘)‘");
418         }
419     }
420     _stkOperators.pop();
421     pToken++;
422 }
423 
424 // main.cpp
425 #include "calculator.h"
426 
427 int main(int argc, char *argv[])
428 {
429     Calculator calculator;
430 
431     if (argc > 1)
432     {
433         if (argc == 2)
434         {
435             calculator.parseExpression(string(argv[1]));
436             cout << calculator.calculate() << endl;
437         }
438         else
439         {
440             cout << "too many arguments" << endl;
441         }
442     }
443     else
444     {
445         while (1)
446         {
447             string expression;
448             cout << ">" << flush;
449             cin >> expression;
450             if (expression == "quit;")
451             {
452                 cout << "Bye." << endl;
453                 return 0;
454             }
455             try
456             {
457                 calculator.parseExpression(expression);
458                 cout << calculator.calculate() << endl;
459             }
460             catch (string ex)
461             {
462                 cout << ex << endl;
463             }
464         }
465     }
466 }

表达式求值(二叉树方法/C++语言描述)(四)