P1175 表达式的转换 题解
xuhanxi_dada117 · · 题解
艾玛表达式树高斯我了
P1175 表达式的转换
题目描述
平常我们书写的表达式称为中缀表达式,因为它将运算符放在两个操作数中间,许多情况下为了确定运算顺序,括号是不可少的,而后缀表达式就不必用括号了。
后缀标记法:书写表达式时采用运算紧跟在两个操作数之后,从而实现了无括号处理和优先级处理,使计算机的处理规则简化为:从左到右顺序完成计算,并用结果取而代之。
例如:8-(3+2*6)/5+4 可以写为:8 3 2 6 * + 5 / - 4 +
其计算步骤为:
8 3 2 6 * + 5 / - 4 +
8 3 12 + 5 / - 4 +
8 15 5 / - 4 +
8 3 - 4 +
5 4 +
9
编写一个程序,完成这个转换,要求输出的每一个数据间都留一个空格。
题目大意
给你一个表达式,让你写成后缀形式,然后输出解的过程。
(这题很离谱,前方高能!)
题目解法
表达式转后缀化简,表达式树裸题了
建树
最烦的一步
先找根:
有加减找最后一个加减,
有乘除找最后一个乘除,
否则找第一个幂(找最后一个
注意括号内要看成一个整体(不然递归到后面会出错) 但是!!
如果整个柿子是形如
一定要是对应!!否则
找到根就好做了,直接分开两边继续递归就行了。 最后我们要知道:
- 树的结构
- 叶子结点的数值
- 每个节点的符号(叶子结点就是" ")
计算+输出答案
从根节点开始往下搜,搜出可以算的节点就算(一定在叶子附近),计算完了对树后序遍历输出就好了。
(注:你可能还要写一个武则天计算器)
详情请见注释
代码
嗨害嗨
#include<bits/stdc++.h>
#define N 114514
using namespace std;
string op;
char ch[N];int num[N],lf[N],rf[N],cnt=0;// ch是运算符,num是值,cnt是节点个数,lf,rf左右儿子
void build(int l,int r){//建表达式树
if(l==r){
num[++cnt]=op[l]-'0';
ch[cnt]=' ';
return;
}//叶子结点存好
if(op[l]=='('){//判断是否为(xxxxx)型
int go=1;
for(int i=l+1;i<=r;++i){
if(op[i]=='(') ++go;
else if(op[i]==')') --go;
if(go==0){//找到对应的')'了
if(i==r) ++l,--r;//判断是否为首尾
break;
}
}
}
int p,typo=5;//p为根的坐标
//typo:+1-1*2/2^3
for(int i=r;i>=l;--i){
if(op[i]==')'){//跳过括号
int go=1,j;
for(j=i-1;j>=l;--j){
if(op[j]==')') ++go;
else if(op[j]=='(') --go;
if(go==0) break;
}
i=j;continue;
}else if(op[i]<='9'&&op[i]>='0') continue;//跳过数字
else{//对符号分类讨论
if((op[i]=='+'||op[i]=='-')&&typo>1) p=i,typo=1;//有加减就加减
else if((op[i]=='*'||op[i]=='/')&&typo>2) p=i,typo=2;//有乘除就乘除
else if(op[i]=='^'&&typo>3) p=i,typo=4;//找幂
}
}
int x=++cnt;
ch[x]=op[p];//更新自己
lf[x]=cnt+1;
build(l,p-1);//向左子树递归
rf[x]=cnt+1;
build(p+1,r);//向右子树递归
}
int calc(int a,int b,char gk){
switch(gk){
case '+':return a+b;
case '-':return a-b;
case '*':return a*b;
case '/':return a/b;
case '^':return pow(a,b);
}
}//武则天计算器
void print(int u){//后序遍历输出
if(ch[u]==' '){
cout<<num[u]<<" ";
return;
}
print(lf[u]);print(rf[u]);
cout<<ch[u]<<" ";
}
void dfs(int x){//递归计算
if(ch[x]==' ') return;
dfs(lf[x]);dfs(rf[x]);//算左右子树
num[x]=calc(num[lf[x]],num[rf[x]],ch[x]);//计算本节点
ch[x]=' ';//复位叶子
print(1);cout<<endl;//输出运算过程
}
int main(){
cin>>op;
build(0,op.size()-1);
print(1);cout<<endl;
dfs(1);
return 0;
}
珍爱账号,远离抄袭!
(记得点赞