1. 问题描述
表达式是数据运算的基本方式。人们书写习惯是中缀式如:11+22*(7-4)/3。中缀式的计算是按照运算符的优先级及括号优先的原则,相同级别从左到右计算。表达式还有后缀式(如:22 7 4 / 11 +)和前缀式(如:+ 11 / * 22 – 7 4 3)。后缀表达式和前后最表达式中没有括号给计算带来方便。如后缀式计算时按运算符出现的先后顺序进行计算。本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。
2. 问题描述
基本要求
从文件或键盘读入中缀表达式。
设计操作数为多位整数,如加,减,乘,除,求模的中缀表达式求值算法。
设计将中缀表达式转化为后缀表达式的算法
设计将中缀表达式转化为后缀表达式的算法
设计后缀表达式的求值算法
设计前缀表达式求值的算法
输出各种形式的表达式
扩展运算符集,如增加乘方,单目减,指数等.
3.设计方法
使用二叉树
4.模拟过程
首先,在纸上画出一棵二叉树,叶子节点填入操作数,非叶子节点填入操作符。
通过先序,中序,后序遍历的方法写出树的先序列,中序列,后序列。
通过上述模拟过程来设计构造表达式的二叉树。
利用递归的特点,采用自下向上依次返回节点运算结果,最终实现计算,此点是实现计算的方法,也是此课题的难点,下面会详细介绍。(‘#’构造二叉树的时候空的标志)
测试项目 | 测试用例 | 逻辑表达式 | 预期结果 |
---|---|---|---|
基本测试 | + - 123 # # 29 # # * / 31 # # 3 # # % 13 # # 5 # # | 123 – 29 + 31 / 3 *(13 % 5) | 124 |
扩展测试 | + - / ^ 18 # # 3 # # 9 # # 13 # # * 19 # # % 11 # # l 18 # # 3 # # | 18^3 – 13 + (19 * (11 %(log18/log3))) | 654 |
5代码设计
/*ExTree.h*/
#pragma once
#ifndef __EXTREE__
#define __EXTREE__
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <math.h>
#define DIGIT 10 //结果最大位数
using namespace std;
template < class T >
class ExTree; //表达式树声明
template < class T >
struct Node; //表达式节点声明
enum prior; //优先级枚举声明
char* itoa_my( int value , char* string , int radix ); //整数转字符串函数声明
template < class T >
prior priority( Node<T>*& node_a , Node<T>*& node_b ); //优先级函数声明
template<class T>
int _doMult( T oper_a , T oper_b ); // 乘法
template<class T>
int _doDivi( T oper_a , T oper_b ); // 除法
template<class T>
int _doRema( T oper_a , T oper_b ); // 余数
template<class T>
int _doPlus( T oper_a , T oper_b ); // 加法
template<class T>
int _doSubt( T oper_a , T oper_b ); // 加法
template<class T>
int _doPowe( T oper_a , T oper_b ); // 乘方
template<class T>
int _doLoga( T oper_a , T oper_b ); // 对数
template<class T>
int _doSSub( T oper_a ); //单目减法
template<class T>
int _do_binary_operations( T oper_a, T oper_b , char _operator ); //二元运算
template<class T>
int _do_onemem_operations( T oper_a , char _operator ); //一元运算
vector<string> pr_sequence; //存储先序序列
vector<string> in_sequence; //存储中序序列
vector<string> po_sequence; //存储后序序列
enum prior //优先级枚举量
{
great,
not_great
};
template <class T>
struct Node //表达式树节点
{
Node<T>* left;
T data;
Node<T>* right;
};
template < class T >
class ExTree //表达式树定义
{
public:
ExTree() //构造函数
:root(NULL)
{
}
explicit ExTree(const ExTree<T>& e) //拷贝构造函数
:root(e.root)
{
}
ExTree<T>& operator = (const ExTree<T>& e); //重载赋值运算符
void creatTree(Node<T>*& node); //创建表达式树
void creatTree(Node<T>*& node, ifstream& file); //创建表达式树
ExTree<T>& prExpre(); //前缀表达式
ExTree<T>& inExpre(); //中缀表达式
ExTree<T>& poExpre(); //后缀表达式
ExTree<T>& poValue(); //后缀表达式及求值
ExTree<T>& prValue(); //前缀表达式及求值
ExTree<T>& inValue(); //中缀表达式及求值
T expreValue(); //转换表达式求值
void exprStyle(); //输出三种表达式
bool deleteExTree( Node<T>*& node ); //清空表达式树
Node<T>*& getRoot();//得到根节点
bool inTrav(Node<T>*& node, vector<Node<T>*>& node_vector) const; //中缀遍历
friend prior priority(Node<T>*& node_a, Node<T>*& node_b);//运算符优先级函数
friend int _doMult(T oper_a, T oper_b); //做乘法
friend int _doDivi(T oper_a, T oper_b); //做除法
friend int _doRema(T oper_a, T oper_b); //做余数
friend int _doPlus(T oper_a, T oper_b); //做加法
friend int _doSubt(T oper_a, T oper_b); //做加法
friend int _doPowe(T oper_a, T oper_b); //做乘方
friend int _doLoga(T oper_a, T oper_b); //做对数
friend int _doSSub(T oper_a); //单目减
friend int _do_onemem_operations(T oper_a, char _operator);//做一元运算
friend int _do_binary_operations(T oper_a, T oper_b , char _operator);//做二元运算
~ExTree();
//较高要求:...
private:
Node<T>* root;
bool inToPo(Node<T>*& node) const; //中缀转化为后缀
bool inToPr(Node<T>*& node) const; //中缀转化为前缀
bool inToIn(Node<T>*& node) const; //中缀
T in_cal(Node<T>*& node);//做计算
void _doconversion(); //表达式树转先中后序列函数
};
template<class T>
inline
ExTree<T>& ExTree<T>::operator = (const ExTree<T>& e) //重载赋值运算符
{
root = e.root;
return *this;
}
template<class T>
inline
T ExTree<T>::expreValue() //表达式求值--中缀原理
{
return in_cal(root);
}
template<class T>
inline
bool ExTree<T>::inToPo(Node<T>*& node) const //中缀转化后缀
{
if (node)
{
inToPo(node->left);
inToPo(node->right);
if ((node->data).size() != 0)
po_sequence.push_back(node->data);
}
return true;
}
template<class T>
inline
bool ExTree<T>::inToPr(Node<T>*& node