后缀表达式转换总结

中缀转后缀

1.维护一个符号栈
2.对于数字,直接加入结果ans
3.对于左括号,直到遇到右括号,把括号中间的数字全部添加到结果ans
4.大于栈顶元素则push,小于则pop。(大进小出)
5.弹出栈中其他符号

由于没有对数字相连进行处理,只能处理单个数组的情况

int pr(char o)//传入操作符,返回优先级
{
    int pri[10]={0,0,1,1,2,2,3};//priority
    char op[10]={'#','(','+','-','*','/','^'};
    for(int i=0;i<6;i++)
        if(op[i]==o)return pri[i];
}

string infix_to_postfix(string in)//中缀转后缀
{
    string ans="";
    stack<char>s;
    s.push('#');//作栈底使用
    for(int i=0;i<in.length();i++){//处理表达式
        if(in[i]>='0'&&in[i]<='9')ans+=in[i];//处理数字
        else if(in[i]=='(')s.push(in[i]);//处理括号
        else if(in[i]==')'){
            while(s.top()!='(')ans+=s.top(),s.pop();
            s.pop();//左括号
        }
        else{//处理操作符
            if(pr(in[i])>pr(s.top()))s.push(in[i]);
            else{
                while(pr(in[i])<=pr(s.top()))ans+=s.top(),s.pop();
                s.push(in[i]);
            }
        }
    }
    while(s.top()!='#')ans+=s.top(),s.pop();
    return ans;
}

测试样例:8-(3+2*6)/5+4
输出结果:8326*+5/-4+


后缀表达式求值

由于没有对数字相连进行处理,只能处理单个数组的情况

在这里插入图片描述

遇到符号,则把栈顶元素和次栈顶元素拿出去运算即可。由于进栈导致顺序倒置,所以是运算规则 : 次栈顶元素 操作符 栈顶元素

int calc(int num_a,char o,int num_b)
{
    switch(o){
        case '+':return num_a+num_b;
        case '-':return num_a-num_b;
        case '*':return num_a*num_b;
        case '/':return num_a/num_b;
        case '^':return pow(num_a,numb_b);
    }
}

int calc_postfix(string in)
{
    stack<int>s;
    for(int i=0;i<in.length();i++){
        if(in[i]>='0'&&in[i]<='9')s.push(in[i]-'0');
        else {
            int b = s.top();s.pop();
            int a = s.top();s.pop();
            s.push(calc(a,in[i],b));
        }
    }
    return s.top();
}

单位数的中缀求值

把前面两个步骤合并起来

#include<bits/stdc++.h>
using namespace std;

string str;
int pr(char o)//传入操作符,返回优先级
{
    int pri[10]={0,1,1,2,2,3};//priority
    char op[10]={'#','+','-','*','/'};
    for(int i=0;i<6;i++)
        if(op[i]==o)return pri[i];
}

string infix_to_postfix(string in)//中缀转后缀
{
    string ans="";
    stack<char>s;
    s.push('#');//作栈底使用
    for(int i=0;i<in.length();i++){//处理表达式
        if(in[i]>='0'&&in[i]<='9')ans+=in[i];//处理数字
        else if(in[i]=='(')s.push(in[i]);//处理括号
        else if(in[i]==')'){
            while(s.top()!='(')ans+=s.top(),s.pop();
            s.pop();//左括号
        }
        else{//处理操作符
            if(pr(in[i])>pr(s.top()))s.push(in[i]);
            else{
                while(pr(in[i])<=pr(s.top()))ans+=s.top(),s.pop();
                s.push(in[i]);
            }
        }
    }
    while(s.top()!='#')ans+=s.top(),s.pop();
    return ans;
}

int calc(int num_a,char o,int num_b)
{
    switch(o){
        case '+':return num_a+num_b;
        case '-':return num_a-num_b;
        case '*':return num_a*num_b;
        case '/':return num_a/num_b;
    }
}

int calc_postfix(string in)
{
    stack<int>s;
    for(int i=0;i<in.length();i++){
        if(in[i]>='0'&&in[i]<='9')s.push(in[i]-'0');
        else {
            int b = s.top();s.pop();
            int a = s.top();s.pop();
            s.push(calc(a,in[i],b));
        }
    }
    return s.top();
}

int main()
{
    cin>>str;
    cout<<calc_postfix(infix_to_postfix(str))<<endl;
    return 0;
}

表达式中多位数处理

思路:对读入的中缀表达式进行预处理,将数字分开。计算时以@作为分割符来读取数。

#include<bits/stdc++.h>
using namespace std;

string str;
int pr(char o)//传入操作符,返回优先级
{
    int pri[10]={0,0,1,1,2,2,3};//priority
    char op[10]={'#','(','+','-','*','/','^'};
    for(int i=0;i<6;i++)
        if(op[i]==o)return pri[i];
}

int is_op(char o)//判断是否为符号
{
    if(o>='0'&&o<='9')return 0;
    return 1;
}

string exp_deal(string in)//对表达式进行处理,防止数字相连,这里以@分隔
{
    string deal="";
    for(int i=0;i<in.length();i++){
        deal+=in[i];
        if(in[i]>='0'&&in[i]<='9'&&is_op(in[i+1]))deal+='@';
    }
    return deal;
}

string infix_to_postfix(string in)//中缀转后缀
{
    in=exp_deal(in);//对多位数字进行处理
    string ans="";
    stack<char>s;
    s.push('#');//作栈底使用
    for(int i=0;i<in.length();i++){//处理表达式
        if(in[i]>='0'&&in[i]<='9'||in[i]=='@')ans+=in[i];//处理数字
        else if(in[i]=='(')s.push(in[i]);//处理括号
        else if(in[i]==')'){
            while(s.top()!='(')ans+=s.top(),s.pop();
            s.pop();//左括号
        }
        else{//处理操作符
            if(pr(in[i])>pr(s.top()))s.push(in[i]);
            else{
                while(pr(in[i])<=pr(s.top()))ans+=s.top(),s.pop();
                s.push(in[i]);
            }
        }
    }
    while(s.top()!='#')ans+=s.top(),s.pop();
    return ans;
}

int calc(int num_a,char o,int num_b)
{
    switch(o){
        case '+':return num_a+num_b;
        case '-':return num_a-num_b;
        case '*':return num_a*num_b;
        case '/':return num_a/num_b;
        case '^':return (int)pow(num_a,num_b);
    }
}

int calc_postfix(string in)
{
    stack<int>s;
    int num=0;
    for(int i=0;i<in.length();i++){
        if(in[i]>='0'&&in[i]<='9')
            num = num*10+(in[i]-'0');
        else if(in[i]=='@')
            s.push(num),num=0;
        else {
            int b = s.top();s.pop();
            int a = s.top();s.pop();
            s.push(calc(a,in[i],b));
        }
    }
    return s.top();
}


int main()
{
    cin>>str;
    cout<<calc_postfix(infix_to_postfix(str))<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值