前言
最近在系统复习刷题单,做到了本应滚瓜烂熟的表达式转换的题,忘记了出栈入栈的规则,调了很久也没有过。
最后怒写了一棵表达式树过了,个人认为这个方法便于记忆,也比较好写。
代码
核心流程就是在区间中寻找最后一个运算的运算符,然后将这个运算符作为根,递归左右区间进行建树,叶子节点全部为操作数。
如果区间内不存在运算符,就一定只有一个数字,读入数字作为叶子节点。
代码:以洛谷P1175为例
#include <bits/stdc++.h>
using namespace std;
string s1;
int pr;
int len;
int cnt;
struct node{
int now;
int lson;
int rson;
int flag;
int val;
char ch;
}node[100005];
int build(int l,int r){
cnt++;
int now1=cnt;
node[cnt].now=cnt;
int min1=1000;
int min2=0;
int pr=0;
for(int i=l;i<=r;i++){ //寻找最后一个运算的运算符
if(s1[i]=='-'||s1[i]=='+'){
if(pr<=min1){
min1=pr;
min2=i;
}
}
else if(s1[i]=='*'||s1[i]=='/'){
if(pr+1<=min1){
min1=pr+1;
min2=i;
}
}
else if(s1[i]=='^'){
if(pr+2<=min1){
min1=pr+2;
min2=i;
}
}
else if(s1[i]=='('){
pr+=3;
}
else if(s1[i]==')'){
pr-=3;
}
}
if(min1==1000){ //否则读入数据
int sz=0;
for(int i=l;i<=r;i++){
if(s1[i]<='9'&&s1[i]>='0'){
sz*=10;
sz+=s1[i]-'0';
}
}
node[now1].val=sz;
node[now1].flag=0;
}
else{
node[now1].lson=build(l,min2-1);
node[now1].rson=build(min2+1,r);
node[now1].flag=1;
node[now1].ch=s1[min2];
}
return now1;
}
void tran(int now){ //后序遍历转化为后缀表达式
if(now==0)return;
tran(node[now].lson);
tran(node[now].rson);
if(node[now].flag==1){
cout<<node[now].ch<<' ';
}
else{
cout<<node[now].val<<' ';
}
return;
}
int cnt1;
int flag1;
deque<pair<int,int> > q1; //依次输出每一步运算结果要用到
void tran1(int now){
if(now==0)return;
tran1(node[now].lson);
tran1(node[now].rson);
if(node[now].flag==1){
if(flag1==0){
node[now].flag=0;
if(node[now].ch=='+'){
node[now].val=node[node[now].lson].val+node[node[now].rson].val;
}
else if(node[now].ch=='-'){
node[now].val=node[node[now].lson].val-node[node[now].rson].val;
}
else if(node[now].ch=='*'){
node[now].val=node[node[now].lson].val*node[node[now].rson].val;
}
else if(node[now].ch=='/'){
node[now].val=node[node[now].lson].val/node[node[now].rson].val;
}
else if(node[now].ch=='^'){
node[now].val=(int)pow(node[node[now].lson].val,node[node[now].rson].val);
}
node[now].lson=node[now].rson=0;
q1.pop_back();
q1.pop_back();
q1.push_back(make_pair(0,node[now].val));
flag1=1;
}
else{
q1.push_back(make_pair(1,node[now].ch));
}
}
else{
q1.push_back(make_pair(0,node[now].val));
}
return;
}
int main(){
cin>>s1;
len=s1.length();
for(int i=0;i<len;i++){
if(s1[i]=='-'||s1[i]=='+'||s1[i]=='*'||s1[i]=='/'||s1[i]=='^')cnt1++;
}
int root=build(0,len-1);
tran(root);
cout<<endl;
for(int i=1;i<=cnt1;i++){
flag1=0;
tran1(root);
while(!q1.empty()){
int temp=q1.front().first;
if(temp==0){
cout<<q1.front().second<<' ';
}
else{
cout<<(char)q1.front().second<<' ';
}
q1.pop_front();
}
cout<<endl;
}
}