中缀转后缀:
初始化栈s,s表示符号栈,用来存放中间符号
步骤:
- 从前往后依次循环处理每个字符
- 若当前字符为操作数(数字或字母),直接输出(后缀表达式中操作数顺序与原序相同)
- 若当前字符为运算符或括号,分三种情况处理
- 若栈s为空或当前处理字符为左括号,直接入栈s
- 若当前处理字符为右括号,s不断出栈(有个循环)输出,直到读到左括号,左括号直接舍弃
- 其他情况则要比较当前处理字符和s栈顶字符的优先级
- 若当前处理字符优先级高,则入栈s
- 其他情况(当前处理字符优先级小于等于栈顶字符优先级)s不断出栈(有个循环)并输出
- 所有字符处理完,将栈s所有字符输出
中缀转前缀:
初始化两个栈s1,s2,s1表示符号栈,用来存放中间符号,s2用来存放前缀表达式。
步骤:
- 从后往前依次循环处理每个字符
- 若当前字符为操作数(数字或字母),直接入栈s2
- 若当前字符为运算符或括号,分三种情况处理
- 若栈s1为空或当前处理字符为右括号,直接入栈s1
- 若当前处理字符为左括号,s1不断出栈(有个循环)并入栈s2,直到读到右括号,右括号直接舍弃
- 其他情况则要比较当前处理字符和s1栈顶字符的优先级
- 若当前处理字符优先级大于等于栈顶字符优先级,则入栈s1
- 其他情况(当前处理字符优先级低于栈顶字符优先级)s1不断出栈(有个循环)并入栈s2
- 将栈s1中剩余字符不断出栈并入栈s2
- 将栈s2元素依次输出即可
编程易错:
判断当前处理字符与栈顶字符优先级高低时,将栈非空的判断放在前面,否则栈空时会报错
#include <iostream>
#include <stack>
#include <string>
#include <map>
using namespace std;
int main(int argc, char *argv[]) {
string str;
map<char, int> priority;
priority['+'] = 0;
priority['-'] = 0;
priority['*'] = 1;
priority['/'] = 1;
while(getline(cin, str)){
stack<char> s1;//符号栈
stack<char> s2;
char ch;
int i;
for(i = str.size() - 1; i >= 0; --i){
if(('0' <= str[i] && str[i] <= '9')
|| ('a' <= str[i] && str[i] <= 'z')
|| ('A' <= str[i] && str[i] <= 'Z')){//数字直接入栈
s2.push(str[i]);
}
else{//运算符或括号
if(s1.size() == 0 || str[i] == ')'){//栈空及字符为右括号直接入栈
s1.push(str[i]);
}else if(str[i] == '('){//字符为左括号时不断出栈,直到右括号出栈,并进s2栈,括号舍弃
while(!s1.empty() && s1.top() != ')'){
ch = s1.top();
s1.pop();
s2.push(ch);
}
s1.pop();//右括号舍弃
}else{
if(priority[str[i]] < priority[s1.top()]){//栈顶运算符优先级高
while(!s1.empty() && priority[str[i]] < priority[s1.top()]){//易错:要将栈非空的判断放在前面,否则在栈空时会报错
ch = s1.top();
s1.pop();
s2.push(ch);
}
s1.push(str[i]);
}else{
s1.push(str[i]);
}
}
}
}
while(!s1.empty()){//符号栈剩余符号压入s2栈中
ch = s1.top();
s1.pop();
s2.push(ch);
}
while(!s2.empty()){
ch = s2.top();
s2.pop();
cout<<ch;
}
cout<<endl;
}
return 0;
}