一个算术表达式的计算语义可以用二叉树唯一的表示出来。假设算术表达式的语义二叉树已经给出,请编码实现算术表达式的中缀形式(保持计算语义)的输出,并计算出该表达式的值。
要求:
1)使用二叉树的完全前序序列建立表达式的语义二叉树,空子树用符号@表示;
2)算术运算符包括:+, -, * , / ; 运算量只考虑单数字字符(1位整数)
3 ) 输出时用括号该表优先级;
4) 如果结果有小数,小数点后保留5位;
提示:
1)递归执行下列步骤即可求值:先分别求出左子树和右子树表示的子表达式的值,最后根据根结点的运算符的要求,计算出表达式的最后结果。
2)二叉树的中序遍历序列与原算术表达式基本相同,但是需要将中序序列加上括号,即当根结点运算符优先级高于左子树(或右子树)根结点运算符时,就需要加括号。
例如:
输入:*
2@@-3@@1@@
输出:
2*(3-1)=4
输入
-*-7@@5@@+/4@@6@@-3@@*5@@2@@+/7@@3@@9@@
输出
(7-5)*(4/6+3-5*2)-(7/3+9)=-24
输入
-*-5@@7@@+/4@@6@@-3@@*5@@2@@+/7@@3@@9@@
输出
(5-7)*(4/6+3-5*2)-(7/3+9)=1.33333
#include<bits/stdc++.h>
using namespace std;
string eqn="";//最终生成带括号的中缀表达式
int priority[130]={
0};
void getPriority()//栈运算的优先级
{
priority['+']=1;
priority['-']=1;
priority['*']=2;
priority['/']=2;
}
int cmp(char theta1,char theta2)//栈运算的优先级比较
{
return priority[theta1]-priority[theta2];
}
bool cmp(char c1,char c2,int l_or_r)//二叉树加括号的优先级比较
{
if(l_or_r==1&&c2=='-')return false;
else if((c1=='+'||c1=='-')&&(c2=='*'||c2=='/'||c2=='-'))return true;
else if((c1=='*'&&c2=='/')||(c1=='/'&&c2=='/'))return true;
else return false;
}
template<class T>//模板类
class Stack//栈
{
private:
T a[105];
int up,down;
public:
Stack(){
up=0;down=0;}
void Push(T x){
a[up++]=x;}
void Pop(){
up--;}
T Top(){
return a[up-1];}
int Size(){
return up-down;}
bool Empty(){
return up==down?true:false;}
};
typedef struct node//结点类
{
char data;
struct node*leftchild,*rightchild;
}Node;
class BinTree//二叉树类
{
public:
Node*root;
void create(Node*&t);//建立二叉树
void travel(Node*subtree,char c,int l_or_r);//遍历二叉树并获取带括号的中缀表达式
};
void BinTree::create(Node*&t)
{
char ch;
cin>>ch;
if(ch=='@') t=NULL;
else
{
t=new Node;
t->data=ch;
create(t->leftchild);
create(t->rightchild);
}
}
void BinTree::travel(Node*subtree,char c,int l_or_r)
{
if(subtree!=NULL)
{
if(!isdigit(subtree->data)&&cmp(subtree->data,c,l_or_r))eqn+="(";
travel(subtree->leftchild,subtree->data,1);
eqn+=subtree->data;
travel(subtree->rightchild,subtree->data,0);
if(!isdigit(subtree->data)&&cmp(subtree->data,c,l_or_r))eqn+=")";
}
}
Stack<double>num;
Stack<char>op;
double cal(double num1,double num2,char op)//4种运算
{
if(op=='+')return num1+num2;
else if(op=='-')return num1-num2;
else if(op=='*')return num1*num2;
else if(op=='/')return num1/num2;
}
int main()
{
BinTree btree;
getPriority();
btree.create(btree.root);
btree.travel(btree.root,' ',2);
int i;
double a,b;
for(i=0;i<=eqn.length()-1;i++)
{
if(eqn[i]>='0'&&eqn[i]<='9')num.Push(eqn[i]-'0');
else if(eqn[i]=='+'||eqn[i]=='-'||eqn[i]=='*'||eqn[i]=='/'||eqn[i]=='('||eqn[i]==')')
{
if(op.Empty()||eqn[i]=='('||op.Top()=='('||cmp(op.Top(),eqn[i])<0)op.Push(eqn[i]);
else if(eqn[i]==')')
{
while(op.Top()!='(')
{
a=num.Top();
num.Pop();
b=num.Top();
num.Pop();
num.Push(cal(b,a,op.Top()));
op.Pop();
}
op.Pop();
}
else if(cmp(op.Top(),eqn[i])>=0)
{
while(cmp(op.Top(),eqn[i])>=0)
{
a=num.Top();
num.Pop();
b=num.Top();
num.Pop();
num.Push(cal(b,a,op.Top()));
op.Pop();
if(op.Empty())break;
}
op.Push(eqn[i]);
}
}
}
while(!op.Empty())
{
a=num.Top();
num.Pop();
b=num.Top();
num.Pop();
num.Push(cal(b,a,op.Top()));
op.Pop();
}
cout<<eqn;
printf("=");
if(abs(num.Top())-(int)abs((num.Top()))<=1e-7)printf("%d",(int)num.Top());
else printf("%.5f",num.Top());
return 0;
}