中缀表达式转化为后缀表达式的过程详解及其实现代码

中缀表达式和后缀表达式的概念

中缀表达式:操作符以中缀形式处于操作数的中间,例:1 + 2。

后缀表达式:将运算符写在操作数之后,例:12+。

一个表达式E的后缀形式可以如下定义:

  1. 如果E是一个变量或常量,则E的后缀式是E本身。
  2. 如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后缀式为E1’E2’ op,这里E1’和E2’分别为E1和E2的后缀式。
  3. 如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。

那么为什么要将中缀表达式变为后缀表达式呢?
与后缀表达式相比,中缀表达式不容易被计算机解析,后缀表达式更易于计算机计算。

中缀表达式转化为后缀表达式的过程

将一个中缀表达式转换为后缀表达式的一般算法:

首先需要分配一个栈,作为临时存储运算符的栈S(含一个结束符号)。

将 ‘#’ 入栈S,作为结束符号,然后从左至右开始扫描中缀表达式:

  1. 若取出的字符是操作数,则加入后缀表达式
  2. 若取出的字符是运算符:
    a. 若为’(’,入栈;
    b. 若为’)’,则依次把栈中的运算符加入后缀表达式,直到出现’)’,然后从栈中删除’(’;
    c. 若为除了括号之外的其他运算符,当其优先级高于栈顶的运算符时,直接入栈; 否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到遇到一个比它优先级低或遇到了一个左括号为止。

运算符的优先级如下表所示:
isp(in stack priority)是栈内优先级,icp(in coming priority)是栈外优先级

操作符#(*, /+,-)
isp01536
icp06421

实例及详细过程

例一: 将中缀表达式a+b-a*((c+d)/e-f)+g转换为等价的后缀表达式。

步骤扫描项动作栈内内容当前后缀表达式
0'#'进栈,读下一个符号#
1a直接输出#a
2+isp(’#’) < icp(’+’),进栈#+a
3b直接输出#+ab
4-isp(’+’) > icp(’-’),退栈并输出#ab+
5isp(’#’) < icp(’-’),进栈#-ab+
6a直接输出#-ab+a
7*isp(’-’) < icp(’*’),进栈#-*ab+a
8(isp(’*’) < icp(’(’),进栈#-*(ab+a
9(isp(’(’) < icp(’(’),进栈#-*((ab+a
10c直接输出#-*((ab+ac
11+isp(’(’) < icp(’+’),进栈#-*((+ab+ac
12d直接输出#-*((+ab+acd
13)isp(’+’) > icp(’)’) ,退栈并输出#-*((ab+acd+
14isp(’(’) == icp(’)’),退栈#-*(ab+acd+
15/isp(’() < icp(’/’),进栈#-*(/ab+acd+
16e直接输出#-*(/ab+acd+e
17-isp(’/’) > icp(’-’),退栈并输出#-*(ab+acd+e/
18isp(’(’) < icp(’-’),进栈#-*(-ab+acd+e/
19f直接输出#-*(-ab+acd+e/f
20)isp(’-’) > icp(’)’),退栈并输出#-*(ab+acd+e/f-
21isp(’(’) == icp(’)’),退栈#-*ab+acd+e/f-
22+isp(’*’) > icp(’+’),退栈并输出#-ab+acd+e/f-*
23isp(’-’) > icp(’+’),退栈并输出#ab+acd+e/f-*-
24isp(’#’) < icp(’+’),进栈#+ab+acd+e/f-*-
25g直接输出#+ab+acd+e/f-*-g
26#isp(’+’) > icp(’#’),退栈并输出#ab+acd+e/f-*-g+
27isp(’#’) == icp(’#’),退栈,结束ab+acd+e/f-*-g+

所以,中缀表达式a+b-a*((c+d)/e-f)+g与之对应的后缀表达式为ab+acd+e/f-*-g+

例二: 将中缀表达式a/b+(c*d-e*f)/g转换成等价的后缀表达式

步骤扫描项动作栈内内容当前后缀表达式
0'#'进栈,读下一个符号#
1a直接输出#a
2/isp(’#’) < icp(’/’),进栈#/a
3b直接输出#/ab
4+isp(’/’) > icp(’+’),退栈并输出#ab/
5isp(’#’) < icp(’+’),进栈#+ab/
6(isp(’+’) < icp(’(’),进栈#+(ab/
7c直接输出#+(ab/c
8*isp(’(’) < icp(’*’),进栈#+(*ab/c
9d直接输出#+(*ab/cd
10-isp(’*’) > icp(’-’),退栈并输出#+(ab/cd*
11isp(’(’) < icp(’-’),进栈#+(-ab/cd*
12e直接输出#+(-ab/cd*e
13*isp(’-’) < icp(’*’),进栈#+(-*ab/cd*e
14f直接输出#+(-*ab/cd*ef
15)isp(’*’) > icp(’)’),退栈并输出#+(-ab/cd*ef*
16isp(’-’) > icp(’)’),退栈并输出#+(ab/cd*ef*-
17isp(’(’) == icp(’)’),退栈#+ab/cd*ef*-
18/isp(’+’) < icp(’/’),进栈#+/ab/cd*ef*-
19g直接输出#+/ab/cd*ef*-g
20#isp(’/’) > icp(’#’),退栈并输出#+ab/cd*ef*-g/
21isp(’+’) > icp(’#’),退栈并输出#ab/cd*ef*-g/+
22isp(’#’) == icp(’#’),退栈,结束ab/cd*ef*-g/+

所以,中缀表达式a/b+(c*d-e*f)/g与之对应的后缀表达式为ab/cd*ef*-g/+

中缀表达式转换为后缀表达式的手工做法

以例2给出的中缀表达式为例,中缀表达式转换为后缀表达式的手工做法为:

  1. 按照运算符的优先级对所有的运算单位加括号。 例二: ((a/b) + (((c*d) - (e*f))/g))
  2. 把运算符号移动到对应括号的后面,然后去掉括号。例二: ((ab)/ (((cd)*(ef)*)-g)/+,去掉括号ab/cd*ef*-g/+

中缀表达式转换为后缀表达式的代码实现(字母表达式)

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

//栈内优先级
int isp(char c){
    if(c == '#'){
        return 0;
    }else if(c == '('){
        return 1;
    }else if(c == '+' || c == '-'){
        return 3;
    }else if(c == '*' || c == '/'){
        return 5;
    }else if(c == ')'){
        return 6;
    }
}

//栈外优先级
int icp(char c){
    if(c == '#'){
        return 0;
    }else if(c == '('){
        return 6;
    }else if(c == '+' || c == '-'){
        return 2;
    }else if(c == '*' || c == '/'){
        return 4;
    }else if(c == ')'){
        return 1;
    }
}


int main(){
    string str;
    while(getline(cin,str)){
        stack<char> data;
        stack<char> op;
        op.push('#');
        str += '#';
        int index = 0;
        while(index < str.size()){
            if(isalpha(str[index])){
                data.push(str[index]);
                cout<<data.top()<<" "; //输出字母
                index++;
            }else{
                if(icp(str[index]) == isp(op.top())){
                    op.pop();
                    index++;
                }else if(icp(str[index]) > isp(op.top())){//运算符进栈
                    op.push(str[index]);
                    index++;
                }else{
                    if(op.top() == ')'){ //如果该运算符是右括号,则直接弹出
                        op.pop();
                    }else{
                        cout<<op.top()<<" "; //输出
                        op.pop();
                    }
                }
            }
        }
    }
    return 0;
}
  • 63
    点赞
  • 353
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值