表达式求值(二叉树方法/C++语言描述)(四)
代码清单
- // binarytree.h
- #ifndef BINARYTREE_H
- #define BINARYTREE_H
- template <typename T> class BinaryTree;
- template <typename T>
- class BinaryTreeNode
- {
- public:
- friend class BinaryTree<T>;
- friend class Calculator;
- T _data;
- private:
- BinaryTreeNode<T> * _leftChild;
- BinaryTreeNode<T> * _rightChild;
- };
- template <typename T>
- class BinaryTree
- {
- public:
- BinaryTree()
- {
- _root = nullptr;
- }
- ~BinaryTree()
- {
- destory();
- }
- void preOrder()
- {
- preOrder(_root);
- }
- void inOrder()
- {
- inOrder(_root);
- }
- void postOrder()
- {
- postOrder(_root);
- }
- protected:
- BinaryTreeNode<T> * _root;
- void destory()
- {
- if (_root)
- {
- destory(_root);
- delete _root;
- }
- }
- void destory(BinaryTreeNode<T> * node)
- {
- if (node)
- {
- destory(node->_leftChild);
- destory(node->_rightChild);
- // visit binary tree data
- if (node->_leftChild)
- {
- delete node->_leftChild;
- }
- if (node->_rightChild)
- {
- delete node->_rightChild;
- }
- }
- }
- virtual void preOrder(BinaryTreeNode<T> * node)
- {
- if (node)
- {
- // visit binary tree data
- preOrder(node->_leftChild);
- preOrder(node->_rightChild);
- }
- }
- virtual void inOrder(BinaryTreeNode<T> * node)
- {
- if (node)
- {
- inOrder(node->_leftChild);
- // visit binary tree data
- inOrder(node->_rightChild);
- }
- }
- virtual void postOrder(BinaryTreeNode<T> * node)
- {
- if (node)
- {
- postOrder(node->_leftChild);
- postOrder(node->_rightChild);
- // visit binary tree data
- }
- }
- };
- #endif // BINARYTREE_H
- // calculator.h
- #ifndef CALCULATOR_H
- #define CALCULATOR_H
- #include <cassert>
- #include <string>
- #include <stack>
- #include <iostream>
- #include "binarytree.h"
- using namespace std;
- typedef enum
- {
- BEGIN,
- NUMBER,
- OPERATOR,
- LEFT_BRAC,
- RIGHT_BRAC
- } TokenType;
- class Token
- {
- public:
- TokenType _type;
- union
- {
- char op;
- double num;
- } _data;
- };
- class Calculator : public BinaryTree<Token>
- {
- public:
- void parseExpression(string expression) throw(string);
- double calculate();
- private:
- stack<char> _stkOperators;
- stack<BinaryTreeNode<Token> *> _stkNodes;
- stack<double> _stkNumbers;
- static int priority(char op);
- static double calculate(double d1, char op, double d2) throw(string);
- void postOrder(BinaryTreeNode<Token> * node);
- void calculateStack() throw(string);
- void dealWithNumber(char *&pToken) throw(string);
- void dealWithOperator(char *&pToken) throw(string);
- void dealWithLeftBrac(char *&pToken) throw(string);
- void dealWithRightBrac(char *&pToken) throw(string);
- };
- #endif // CALCULATOR_H
- // calculator.cpp
- #include "calculator.h"
- int Calculator::priority(char op)
- {
- assert(op == '+' || op == '-' || op == '*' || op == '/' || op == '(');
- if (op == '+' || op == '-')
- {
- return ;
- }
- else if (op == '*' || op == '/')
- {
- return ;
- }
- else
- {
- return ;
- }
- }
- double Calculator::calculate(double d1, char op, double d2) throw(string)
- {
- assert(op == '+' || op == '-' || op == '*' || op =='/');
- cout << d1 << op << d2 << endl;
- if (op == '+')
- {
- return d1 + d2;
- }
- else if (op == '-')
- {
- return d1 - d2;
- }
- else if (op == '*')
- {
- return d1 * d2;
- }
- else
- {
- if (!d2)
- {
- throw string("divided by 0");
- }
- return d1 / d2;
- }
- }
- void Calculator::calculateStack() throw(string)
- {
- BinaryTreeNode<Token> * node = new BinaryTreeNode<Token>();
- assert(node);
- node->_data._type = OPERATOR;
- node->_data._data.op = _stkOperators.top();
- _stkOperators.pop();
- assert(!_stkNodes.empty());
- node->_rightChild = _stkNodes.top();
- _stkNodes.pop();
- assert(!_stkNodes.empty());
- node->_leftChild = _stkNodes.top();
- _stkNodes.pop();
- _stkNodes.push(node);
- }
- void Calculator::parseExpression(string expression) throw(string)
- {
- destory();
- while (!_stkNodes.empty())
- {
- _stkNodes.pop();
- }
- while (!_stkOperators.empty())
- {
- _stkOperators.pop();
- }
- TokenType lastToken = BEGIN;
- char * pToken = &expression[];
- while (*pToken)
- {
- switch (lastToken)
- {
- case BEGIN:
- if (*pToken == '(')
- {
- // an expression begin with a left bracket
- dealWithLeftBrac(pToken);;
- lastToken = LEFT_BRAC;
- }
- else
- {
- // or a number
- dealWithNumber(pToken);
- lastToken = NUMBER;
- }
- break;
- case NUMBER:
- // after a number
- if (*pToken == ')')
- {
- // it may be a right bracket
- dealWithRightBrac(pToken);
- lastToken = RIGHT_BRAC;
- }
- else
- {
- // it may be an operator
- dealWithOperator(pToken);
- lastToken = OPERATOR;
- }
- break;
- case OPERATOR:
- case LEFT_BRAC:
- // after an operator or a left bracket
- if (*pToken == '(')
- {
- // it may be a left bracket
- dealWithLeftBrac(pToken);
- lastToken = LEFT_BRAC;
- }
- else
- {
- // it may be a number
- dealWithNumber(pToken);
- lastToken = NUMBER;
- }
- break;
- case RIGHT_BRAC:
- // after a right bracket
- if (*pToken == ')')
- {
- // it may be another right bracket
- dealWithRightBrac(pToken);
- lastToken = RIGHT_BRAC;
- }
- else
- {
- // it may be an perator
- dealWithOperator(pToken);
- lastToken = OPERATOR;
- }
- break;
- }
- }
- while (!_stkOperators.empty())
- {
- if (_stkOperators.top() == '(')
- {
- throw string("bad token '('");
- }
- calculateStack();
- }
- assert(!_stkNodes.empty());
- _root = _stkNodes.top();
- }
- void Calculator::postOrder(BinaryTreeNode<Token> *node)
- {
- if (node)
- {
- postOrder(node->_leftChild);
- postOrder(node->_rightChild);
- // visit binary tree data
- if (node->_data._type == NUMBER)
- {
- _stkNumbers.push(node->_data._data.num);
- }
- else
- {
- assert(!_stkNumbers.empty());
- double d2 = _stkNumbers.top();
- _stkNumbers.pop();
- assert(!_stkNumbers.empty());
- double d1 = _stkNumbers.top();
- _stkNumbers.pop();
- char op = node->_data._data.op;
- _stkNumbers.push(calculate(d1, op, d2));
- }
- }
- }
- double Calculator::calculate()
- {
- while (!_stkNumbers.empty())
- {
- _stkNumbers.pop();
- }
- BinaryTree::postOrder();
- assert(!_stkNumbers.empty());
- return _stkNumbers.top();
- }
- void Calculator::dealWithNumber(char *&pToken) throw(string)
- {
- if (!isdigit(*pToken) && *pToken != '-')
- {
- throw string("bad token '") + *pToken + "'";
- }
- BinaryTreeNode<Token> * node = new BinaryTreeNode<Token>();
- assert(node);
- node->_data._type = NUMBER;
- node->_data._data.num = strtod(pToken, &pToken);
- node->_leftChild = node->_rightChild = nullptr;
- _stkNodes.push(node);
- }
- void Calculator::dealWithOperator(char *&pToken) throw(string)
- {
- if (*pToken != '+' && *pToken != '-' && *pToken != '*' && *pToken != '/')
- {
- throw string("bad token '") + *pToken + "'";
- }
- if (!_stkOperators.empty()
- && priority(_stkOperators.top()) >= priority(*pToken))
- {
- calculateStack();
- }
- _stkOperators.push(*pToken++);
- }
- void Calculator::dealWithLeftBrac(char *&pToken) throw(string)
- {
- if (*pToken != '(')
- {
- throw string("bad token '") + *pToken + "'";
- }
- _stkOperators.push(*pToken++);
- }
- void Calculator::dealWithRightBrac(char *&pToken) throw(string)
- {
- if (*pToken != ')')
- {
- throw string("bad token '") + *pToken + "'";
- }
- while (!_stkOperators.empty() && _stkOperators.top() != '(')
- {
- calculateStack();
- if (_stkOperators.empty())
- {
- throw string("bad token ')'");
- }
- }
- _stkOperators.pop();
- pToken++;
- }
- // main.cpp
- #include "calculator.h"
- int main(int argc, char *argv[])
- {
- Calculator calculator;
- if (argc > )
- {
- if (argc == )
- {
- calculator.parseExpression(string(argv[]));
- cout << calculator.calculate() << endl;
- }
- else
- {
- cout << "too many arguments" << endl;
- }
- }
- else
- {
- while ()
- {
- string expression;
- cout << ">" << flush;
- cin >> expression;
- if (expression == "quit;")
- {
- cout << "Bye." << endl;
- return ;
- }
- try
- {
- calculator.parseExpression(expression);
- cout << calculator.calculate() << endl;
- }
- catch (string ex)
- {
- cout << ex << endl;
- }
- }
- }
- }
表达式求值(二叉树方法/C++语言描述)(四)的更多相关文章
- 表达式求值(二叉树方法/C++语言描述)(二)
表达式二叉树节点的数据可能是运算数或运算符,可以使用一个联合体进行存储:同时还需要一个变量来指示存储的是运算数还是运算符,可以采用和栈方法求值中一样的枚举类型TokenType: typedef en ...
- 表达式求值(二叉树方法/C++语言描述)(一)
使用二叉树对算数表达式(以下简称为表达式)进行求值,实质上是将表达式转换为二叉树,对其进行后序遍历,得到后缀表达式的同时可以求得表达式的值.转换和求值的过程也需要借助数据结构栈的帮助. 二叉树数据结构 ...
- 表达式求值(二叉树方法/C++语言描述)(三)
二叉树方法求值对运算数处理的方法与栈方法求值不太相同,除了将字符串中的运算数转换为浮点类型外,还需要生成新的节点: void Calculator::dealWithNumber(char *& ...
- 表达式求值(二叉树方法/C++语言描述)(五)
本例中的二叉树图是使用Graphviz绘制的(Graphviz官网),在Ubuntu Linux下可以使用apt-get命令安装它: sudo apt-get install graphviz 表达式 ...
- 表达式求值--数据结构C语言算法实现
这篇博客介绍的表达式求值是用C语言实现的,只使用了c++里面的引用. 数据结构课本上的一个例题,但是看起来很简单,实现却遇到了很多问题. 这个题需要构建两个栈,一个用来存储运算符OPTR, 一个用来存 ...
- LeetCode:逆波兰表达式求值【150】
LeetCode:逆波兰表达式求值[150] 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除 ...
- 表达式求值(栈方法/C++语言描述)(二)
上篇中完成了对表达式求值的整体过程,接下来看看如何处理不同类型的token. 对运算数的处理比较简单,它直接调用函数strtod(),将字符串中的运算数转换为浮点类型并将它压入运算数栈中: void ...
- 利用栈实现算术表达式求值(Java语言描述)
利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...
- Java描述表达式求值的两种解法:双栈结构和二叉树
Java描述表达式求值的两种解法:双栈结构和二叉树 原题大意:表达式求值 求一个非负整数四则混合运算且含嵌套括号表达式的值.如: # 输入: 1+2*(6/2)-4 # 输出: 3.0 数据保证: 保 ...
随机推荐
- URLWRITE视图重写技术
UrlRewrite就是地址重写,用户得到的全部都是经过处理后的URL地址,类似于Apache的mod_rewrite.将我们的动态网页地址转化为静态的地址,如html.shtml,还可以隐藏网页的真 ...
- 【PHP】最详细PHP从入门到精通(四)——PHP中的字符串
PHP从入门到精通 之PHP中的字符串 大家好,继续跟进PHP最详尽的知识更新,本周,跟大家重点讲一下PHP中字符串的使用.在PHP中,字符串是非常重要的一个概念,基本上大家想到的字符串的处理功能, ...
- 【知识整理】这可能是最好的RxJava 2.x 入门教程(四)
这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(一) 这可能是最好的RxJava 2.x 入门教程(二) 这可能是最好的RxJava 2. ...
- 关于php的一些安全知识
绝不要以明文形式显示或发送密码.即使是对密码的所有者也应该这样.如果你需要 "忘记密码" 的功能,可以随机生成一个新的 一次性的(这点很重要)密码,然后把这个密码发送给用户 你希望 ...
- EntityFramework.Extended.Update.Ambiguous column name
异常描述 c#代码 dbcontext.Table.Where(x => x.B > 0).Update( x => new Table() { A = x.B } ) 抛出异常: ...
- WCF学习——构建第二个WCF应用程序(六)
一.创建客户端应用程序 若要创建客户端应用程序,你将另外添加一个项目,添加对该项目的服务引用,配置数据源,并创建一个用户界面以显示服务中的数据.若要创建客户端应用程序,你将另外添加一个项目,添加对该项 ...
- MySQL基础语法命令
1. 建表 创建MySQL数据表需要以下信息: 表名 表字段名 定义每个表字段 通用语法: CREATE TABLE table_name (column_name column_type); 实例: ...
- 从Java熟练到Android入门
刚刚从学校出来,唉,从Java转入Android. 当初老师告诉我们Android不重要,结果,Android的所有课不是在玩手机就是在说话,没认真听也没认真看,作业也没认真做,现在想想好后悔啊,以至 ...
- Lniux下安装mysql----编译版
####安装mysql-5.7.10rpm -e --nodeps mysqlrpm -e mysqlclient10useradd -g mysql -s /sbin/nologininstall_ ...
- Vue.js入学教程
Vue.js是什么Vue.js 是用于构建交互式的 Web 界面的库.Vue.js 提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单.灵活的 API.Vue.js(类似于view)是一套构建 ...