• 表达式求值(二叉树方法/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 }
  • 相关阅读:
    CSS Friendly Control Adapters CSSFriendly.dll
    2008秋季计算机软件基础未交实验报告名单
    About NeatHtml™ Brettle.Web.NeatHtml.dll
    What is DotNetOpenMail DotNetOpenMail.dll
    What is the simplest way to distribute a .NET COM server to any platform?
    页面压缩 Enabling Gzip and Deflate HTTP Compression in ASP.NET pages(转)
    [算法分析]计数排序
    [置顶] EJDesktop开源项目
    继承初体验
    [置顶] 基于stm32f103zet6之UC/OS_II的学习1(初步移植OS点灯大法)
  • 原文地址:https://www.cnblogs.com/lets-blu/p/7291556.html
Copyright © 2020-2023  润新知