代码清单

 // 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++语言描述)(四)的更多相关文章

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

    表达式二叉树节点的数据可能是运算数或运算符,可以使用一个联合体进行存储:同时还需要一个变量来指示存储的是运算数还是运算符,可以采用和栈方法求值中一样的枚举类型TokenType: typedef en ...

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

    使用二叉树对算数表达式(以下简称为表达式)进行求值,实质上是将表达式转换为二叉树,对其进行后序遍历,得到后缀表达式的同时可以求得表达式的值.转换和求值的过程也需要借助数据结构栈的帮助. 二叉树数据结构 ...

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

    二叉树方法求值对运算数处理的方法与栈方法求值不太相同,除了将字符串中的运算数转换为浮点类型外,还需要生成新的节点: void Calculator::dealWithNumber(char *& ...

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

    本例中的二叉树图是使用Graphviz绘制的(Graphviz官网),在Ubuntu Linux下可以使用apt-get命令安装它: sudo apt-get install graphviz 表达式 ...

  5. 表达式求值--数据结构C语言算法实现

    这篇博客介绍的表达式求值是用C语言实现的,只使用了c++里面的引用. 数据结构课本上的一个例题,但是看起来很简单,实现却遇到了很多问题. 这个题需要构建两个栈,一个用来存储运算符OPTR, 一个用来存 ...

  6. LeetCode:逆波兰表达式求值【150】

    LeetCode:逆波兰表达式求值[150] 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除 ...

  7. 表达式求值(栈方法/C++语言描述)(二)

    上篇中完成了对表达式求值的整体过程,接下来看看如何处理不同类型的token. 对运算数的处理比较简单,它直接调用函数strtod(),将字符串中的运算数转换为浮点类型并将它压入运算数栈中: void ...

  8. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  9. Java描述表达式求值的两种解法:双栈结构和二叉树

    Java描述表达式求值的两种解法:双栈结构和二叉树 原题大意:表达式求值 求一个非负整数四则混合运算且含嵌套括号表达式的值.如: # 输入: 1+2*(6/2)-4 # 输出: 3.0 数据保证: 保 ...

随机推荐

  1. 关于java反射获取泛型

    public class Test<T> { private final TypeToken<T> typeToken = new TypeToken<T>(get ...

  2. Qt使用MySQL笔记一

    原始日期:2015-08-20 18:01 今天开发项目时,遇到一个问题,经过自己不断尝试,终于找到了解决办法,于是赶紧记下来,不然过段时间可能又忘了呵呵,从而重蹈覆辙,浪费时间~问题是这样的:在插入 ...

  3. mybatis if test 解决页面 升序和降序的问题

    <if test="status !=null and status !='' and status =='1'.toString()"> ORDER BY tag.c ...

  4. js对象中动态读取属性值 动态属性值 js正则表达式全局替换

    $(document).ready(function(){ var exceptionMsg = '${exception.message }'; var exceptionstr = ''; //j ...

  5. js禁止选中(网页复制)

    document.onselectstart=new Function("event.returnValue=false");//禁止选中(无法复制) document.oncon ...

  6. H5学习第一周

    已经接触H5一个周了,经过学习,总算对H5有了一些了解和认知,下面就总结一下我对H5的认知和感悟. 首先接触的是H5的常用标签[meta],它有其以下常用属性 1.charset属性.单独使用,设置文 ...

  7. Java开源博客My-Blog之docker组件化修改

    前言 5月13号上线了自己的个人博客,<Docker+SpringBoot+Mybatis+thymeleaf的Java博客系统开源啦>,紧接着也在github上开源了博客的代码,到现在为 ...

  8. Chrome浏览器扩展开发系列之三:Google Chrome浏览器扩展的架构

    1) 不可视的background页面 Google Chrome扩展往往包含一个不可见的background页面,Google Chrome扩展的主要业务逻辑都位于此.有两种类型的backgroun ...

  9. nodejs 构建本地web测试服务器 以及 解决访问静态资源的问题!

    直接打开html文件,是以file:///方式打开的,这种方式很多时候会遇到跨域的问题,因此我们一般会搭建一个简易的本地服务器,来运行测试页面. 一.构建静态服务器 1.使用express模块 建立个 ...

  10. .NetCore~TagHelpers标签的使用

    回到目录 TagHelpers 能够让服务端代码参与创建和渲染 HTML 元素,让整个View视图看起来只有Html代码,也让前台开发人员开发的页面直接被后台开发人员使用,而不需要重复的书写代码,这种 ...