赞
踩
中缀表达式:操作符以中缀形式处于操作数的中间,例:1 + 2。
后缀表达式:将运算符写在操作数之后,例:12+。
一个表达式E的后缀形式可以如下定义:
那么为什么要将中缀表达式变为后缀表达式呢?
与后缀表达式相比,中缀表达式不容易被计算机解析,后缀表达式更易于计算机计算。
将一个中缀表达式转换为后缀表达式的一般算法:
首先需要分配一个栈,作为临时存储运算符的栈S(含一个结束符号)。
将 ‘#’ 入栈S,作为结束符号,然后从左至右开始扫描中缀表达式:
运算符的优先级如下表所示:
isp(in stack priority)是栈内优先级,icp(in coming priority)是栈外优先级
操作符 | # | ( | *, / | +,- | ) |
---|---|---|---|---|---|
isp | 0 | 1 | 5 | 3 | 6 |
icp | 0 | 6 | 4 | 2 | 1 |
例一: 将中缀表达式a+b-a*((c+d)/e-f)+g转换为等价的后缀表达式。
步骤 | 扫描项 | 动作 | 栈内内容 | 当前后缀表达式 |
---|---|---|---|---|
0 | '#'进栈,读下一个符号 | # | ||
1 | a | 直接输出 | # | a |
2 | + | isp(’#’) < icp(’+’),进栈 | #+ | a |
3 | b | 直接输出 | #+ | ab |
4 | - | isp(’+’) > icp(’-’),退栈并输出 | # | ab+ |
5 | isp(’#’) < icp(’-’),进栈 | #- | ab+ | |
6 | a | 直接输出 | #- | ab+a |
7 | * | isp(’-’) < icp(’*’),进栈 | #-* | ab+a |
8 | ( | isp(’*’) < icp(’(’),进栈 | #-*( | ab+a |
9 | ( | isp(’(’) < icp(’(’),进栈 | #-*(( | ab+a |
10 | c | 直接输出 | #-*(( | ab+ac |
11 | + | isp(’(’) < icp(’+’),进栈 | #-*((+ | ab+ac |
12 | d | 直接输出 | #-*((+ | ab+acd |
13 | ) | isp(’+’) > icp(’)’) ,退栈并输出 | #-*(( | ab+acd+ |
14 | isp(’(’) == icp(’)’),退栈 | #-*( | ab+acd+ | |
15 | / | isp(’() < icp(’/’),进栈 | #-*(/ | ab+acd+ |
16 | e | 直接输出 | #-*(/ | ab+acd+e |
17 | - | isp(’/’) > icp(’-’),退栈并输出 | #-*( | ab+acd+e/ |
18 | isp(’(’) < icp(’-’),进栈 | #-*(- | ab+acd+e/ | |
19 | f | 直接输出 | #-*(- | ab+acd+e/f |
20 | ) | isp(’-’) > icp(’)’),退栈并输出 | #-*( | ab+acd+e/f- |
21 | isp(’(’) == icp(’)’),退栈 | #-* | ab+acd+e/f- | |
22 | + | isp(’*’) > icp(’+’),退栈并输出 | #- | ab+acd+e/f-* |
23 | isp(’-’) > icp(’+’),退栈并输出 | # | ab+acd+e/f-*- | |
24 | isp(’#’) < icp(’+’),进栈 | #+ | ab+acd+e/f-*- | |
25 | g | 直接输出 | #+ | ab+acd+e/f-*-g |
26 | # | isp(’+’) > icp(’#’),退栈并输出 | # | ab+acd+e/f-*-g+ |
27 | isp(’#’) == 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 | '#'进栈,读下一个符号 | # | ||
1 | a | 直接输出 | # | a |
2 | / | isp(’#’) < icp(’/’),进栈 | #/ | a |
3 | b | 直接输出 | #/ | ab |
4 | + | isp(’/’) > icp(’+’),退栈并输出 | # | ab/ |
5 | isp(’#’) < icp(’+’),进栈 | #+ | ab/ | |
6 | ( | isp(’+’) < icp(’(’),进栈 | #+( | ab/ |
7 | c | 直接输出 | #+( | ab/c |
8 | * | isp(’(’) < icp(’*’),进栈 | #+(* | ab/c |
9 | d | 直接输出 | #+(* | ab/cd |
10 | - | isp(’*’) > icp(’-’),退栈并输出 | #+( | ab/cd* |
11 | isp(’(’) < icp(’-’),进栈 | #+(- | ab/cd* | |
12 | e | 直接输出 | #+(- | ab/cd*e |
13 | * | isp(’-’) < icp(’*’),进栈 | #+(-* | ab/cd*e |
14 | f | 直接输出 | #+(-* | ab/cd*ef |
15 | ) | isp(’*’) > icp(’)’),退栈并输出 | #+(- | ab/cd*ef* |
16 | isp(’-’) > icp(’)’),退栈并输出 | #+( | ab/cd*ef*- | |
17 | isp(’(’) == icp(’)’),退栈 | #+ | ab/cd*ef*- | |
18 | / | isp(’+’) < icp(’/’),进栈 | #+/ | ab/cd*ef*- |
19 | g | 直接输出 | #+/ | ab/cd*ef*-g |
20 | # | isp(’/’) > icp(’#’),退栈并输出 | #+ | ab/cd*ef*-g/ |
21 | isp(’+’) > icp(’#’),退栈并输出 | # | ab/cd*ef*-g/+ | |
22 | isp(’#’) == icp(’#’),退栈,结束 | ab/cd*ef*-g/+ |
所以,中缀表达式a/b+(c*d-e*f)/g与之对应的后缀表达式为ab/cd*ef*-g/+
以例2给出的中缀表达式为例,中缀表达式转换为后缀表达式的手工做法为:
#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;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。