问题描述
add(加),sub(减),mult(乘),div(除以),neg(取反),doubleMe(平方)。用二元树来表示(上述)函数式表达式,通过对二元树进行递归处理,对表达式求值,并得到带必要括号的中缀表达式。
【样例输入】
add sub neg 4 12 mult doubleMe 2 5 |
【样例输出】
(-4)-12+(2)^2*5 = 4 |
题解
分为几个模块:1.构建二叉树 2.遍历二叉树输出中缀表达式 3.遍历二叉树递归求值
构建二叉树
二叉树的基本结构
typedef struct bitnode
{
double data;//存储运算符的ascll码和运算数
bitnode *lchild;
bitnode *rchild;
int n;//标记,0为叶子,1为根。因为存储数据时存储的ascll码会产生冲突。
bitnode(int e,int m=0,bitnode *lch=0,bitnode *rch=0):data(e),n(m),lchild(lch),rchild(rch){}//初始化二叉树
}bitnode,*bitree;
定义二叉树的结构体和自定义数据类型(bitnode和*bitree)
当n=0时表示存储的运算数;当n=1时表示存储运算符,用加减乘除的ascll码表示加减乘除,用-1表示取反,用-2表示平方。
递归构建二叉树
用stringstream对象取子串,构建二叉树,首先需要一个判断子串是否为运算数的函数
bool trnum(string s)
bool trnum(string s)
{
int i;
if(s[0]=='+'||s[0]=='-')//可以判断运算数的正负
{
for(i=1;i<s.size()&&isdigit(s[i]);i++);
return i>=s.size();
}
for(i=0;i<s.size()&&isdigit(s[i]);i++);
return i>=s.size();
}
然后就用递归的方法构建二叉树
bitree create(stringstream &x)
{
string w;
x>>w;
if(trnum(w))//操作数,叶子结点
return new bitnode(atoi(w.c_str()));
else //操作符,根结点
{
if(w=="add")
{
bitree t=new bitnode('+',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="sub")
{
bitree t=new bitnode('-',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="mult")
{
bitree t=new bitnode('*',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="div")
{
bitree t=new bitnode('/',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="neg")
{
bitree t=new bitnode(-1,1);
t->lchild=create(x);
t->rchild=NULL;
return t;
}
else if(w=="doubleMe")
{
bitree t=new bitnode(-2,1);
t->lchild=create(x);
t->rchild=NULL;
return t;
}
}
}
遍历二叉树输出中缀表达式
输出过程中要注意括号问题:
bool l(bitree t)//判断左孩子的括号问题
{
bitree t1=t->lchild;
if(t->data=='*'||t->data=='/')
{
if(t1->data=='+'||t1->data=='-')return 1;
else return 0;
}
else return 0;
}
bool r(bitree t)//判断右孩子的括号问题
{
bitree t1=t->rchild;
if(t->data=='+'||t->data=='-')
{
if(t1->data=='+'||t1->data=='-')return 1;
else return 0;
}
else if(t->data=='*'||t->data=='/')return 1;
else return 0;
}
如果是左孩子优先级 <根运算符优先级,则遍历左子树前后,加括号
如果是右孩子优先级 ≤ 根运算符优先级则遍历右子树前后,加括号
用递归的方法输出中缀表达式
void read(bitree t)
{
if(t!=0)//不是空树
{
bitree t1=t->lchild;
if(t1!=0)//左孩子非空
{
if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)//左孩子是运算符(加减乘除)
{
if(l(t))//加括号
{
cout<<"(";read(t1);cout<<")";
}
else read(t1);
}
else if(t->data==-2)//左孩子是平方
{
cout<<"dohbleMe(";
read(t->lchild);
cout<<")";
return;
}
else if(t->data==-1)//左孩子是取反
{
cout<<"("<<"-";
read(t->lchild);
cout<<")";
return;
}
else read(t1);
}
if((t->data=='+'||t->data=='-'||t->data=='*'||t->data=='/')&&t->n==1)cout<<(char)t->data;//如果数据是根结点(操作符)
else cout<<t->data;//如果数据是叶子结点(操作数)
t1=t->rchild;
if(t1!=0)//右孩子非空
{
if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)
{
if(r(t)){
cout<<"(";read(t1);cout<<")";
}
else read(t1);
}
else if(t->data==-2)//左孩子是平方
{
cout<<"dohbleMe(";
read(t->lchild);
cout<<")";
return;
}
else if(t->data==-1)//左孩子是取反
{
cout<<"("<<"-";
read(t->lchild);
cout<<")";
return;
}
else read(t1);
}
}
}
遍历二叉树递归求值
double f(bitree t)
{
if(t!=0)
{
if(t->data=='+'&&t->n==1)return f(t->lchild)+f(t->rchild);
else if(t->data=='-'&&t->n==1)return f(t->lchild)-f(t->rchild);
else if(t->data=='*'&&t->n==1)return f(t->lchild)*f(t->rchild);
else if(t->data=='/'&&t->n==1)return f(t->lchild)/f(t->rchild);
else if(t->data==-1&&t->n==1)return -f(t->lchild);
else if(t->data==-2&&t->n==1)return pow(f(t->lchild),2);
else return t->data;
}
}
源码
#include<iostream>
#include<iostream>
#include<sstream>
#include<fstream>
#include<stdlib.h>
#include<cmath>
using namespace std;
typedef struct bitnode
{
double data;
bitnode *lchild;
bitnode *rchild;
int n;//标记,0为叶子,1为根
bitnode(int e,int m=0,bitnode *lch=0,bitnode *rch=0):data(e),n(m),lchild(lch),rchild(rch){}
}bitnode,*bitree;
bool trnum(string s)
{
int i;
if(s[0]=='+'||s[0]=='-')
{
for(i=1;i<s.size()&&isdigit(s[i]);i++);
return i>=s.size();
}
for(i=0;i<s.size()&&isdigit(s[i]);i++);
return i>=s.size();
}
bitree create(stringstream &x)
{
string w;
x>>w;
if(trnum(w))//操作数,叶子结点
return new bitnode(atoi(w.c_str()));
else //操作符,根结点
{
if(w=="add")
{
bitree t=new bitnode('+',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="sub")
{
bitree t=new bitnode('-',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="mult")
{
bitree t=new bitnode('*',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="div")
{
bitree t=new bitnode('/',1);
t->lchild=create(x);
t->rchild=create(x);
return t;
}
else if(w=="neg")
{
bitree t=new bitnode(-1,1);
t->lchild=create(x);
t->rchild=NULL;
return t;
}
else if(w=="doubleMe")
{
bitree t=new bitnode(-2,1);
t->lchild=create(x);
t->rchild=NULL;
return t;
}
}
}
bool l(bitree t)
{
bitree t1=t->lchild;
if(t->data=='*'||t->data=='/')
{
if(t1->data=='+'||t1->data=='-')return 1;
else return 0;
}
else return 0;
}
bool r(bitree t)
{
bitree t1=t->rchild;
if(t->data=='+'||t->data=='-')
{
if(t1->data=='+'||t1->data=='-')return 1;
else return 0;
}
else if(t->data=='*'||t->data=='/')return 1;
else return 0;
}
void read(bitree t)
{
if(t!=0)//不是空树
{
bitree t1=t->lchild;
if(t1!=0)//左孩子非空
{
if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)//左孩子是运算符(加减乘除)
{
if(l(t))//加括号
{
cout<<"(";read(t1);cout<<")";
}
else read(t1);
}
else if(t->data==-2)//左孩子是平方
{
cout<<"dohbleMe(";
read(t->lchild);
cout<<")";
return;
}
else if(t->data==-1)//左孩子是取反
{
cout<<"("<<"-";
read(t->lchild);
cout<<")";
return;
}
else read(t1);
}
if((t->data=='+'||t->data=='-'||t->data=='*'||t->data=='/')&&t->n==1)cout<<(char)t->data;//如果数据是根结点(操作符)
else cout<<t->data;//如果数据是叶子结点(操作数)
t1=t->rchild;
if(t1!=0)//右孩子非空
{
if((t1->data=='+'||t1->data=='-'||t1->data=='*'||t1->data=='/')&&t1->n==1)
{
if(r(t)){
cout<<"(";read(t1);cout<<")";
}
else read(t1);
}
else if(t->data==-2)//左孩子是平方
{
cout<<"dohbleMe(";
read(t->lchild);
cout<<")";
return;
}
else if(t->data==-1)//左孩子是取反
{
cout<<"("<<"-";
read(t->lchild);
cout<<")";
return;
}
else read(t1);
}
}
}
double f(bitree t)
{
if(t!=0)
{
if(t->data=='+'&&t->n==1)return f(t->lchild)+f(t->rchild);
else if(t->data=='-'&&t->n==1)return f(t->lchild)-f(t->rchild);
else if(t->data=='*'&&t->n==1)return f(t->lchild)*f(t->rchild);
else if(t->data=='/'&&t->n==1)return f(t->lchild)/f(t->rchild);
else if(t->data==-1&&t->n==1)return -f(t->lchild);
else if(t->data==-2&&t->n==1)return pow(f(t->lchild),2);
else return t->data;
}
}
int main()
{
char a[100];
cin.getline(a,100);
stringstream s(a);
bitree t=create(s);
read(t);
cout<<" = "<<f(t);
}
输出结果
欢迎指正!!