中缀表达式转后缀表达式
1 基本概念
在计算机中表达式有三种,前缀表达式(波兰式),中缀表达式,后缀表达式(逆波兰式)。
如表达式:a+b*(c-d)-e/f
前缀表达式:-+a*b-cd/ef
中缀表达式:a+b*(c-d)-e/f
后缀表达式:abcd-*+ef/-
1.1 特点与利弊
中缀表达式的括号必不可少,它的优点是符合我们人类的书写和读取习惯,但缺点是它不方便计算机处理。
前缀和后缀表达式的缺点是不是我们阅读的习惯,但是它们却便于计算机的处理。比如针对后缀表达式来说,它是把操作数一直压入栈中,然后遇到一个操作符的时候,就从栈中取出两个数进行计算,再把得到的结果压入栈中。因此前缀和后缀是非常方便计算机处理的。
现在考虑把中缀表达式转化为后缀表达式或者是从输入的中缀表达式转换为后缀表达式。
2 转换原理
原理不难,我们遇到遇到操作数的时候直接输出,当遇到操作符(包括‘(’,‘+’,‘-’,‘*’,‘/’)的时候,我们需要把符号压入到栈中,
2.1 当遇到‘)’的时候:
我们需要依次从栈顶弹出符号,直到遇到‘(’,并且要将‘(’弹出。如:(a*(b+c)),栈中的是(*(+,当遇到‘)’的时候,我们要弹出‘+’,‘(’。
2.2 当遇到‘(’的时候
此时没什么要说的,直接压栈。
2.3 当遇到‘+’,‘-’,‘*’,‘/’的时候:
我们要把栈顶元素的符号的优先级跟输入的符号的优先级进行对比,如果栈顶优先级高的话,我们就要把栈顶元素依次弹出,直到栈顶的优先级低于输入的优先级或者栈空。
如:a+b+c+d,跟a+b*c+d得到的符号顺序就不一样,原因就是这个优先级的问题。
2.4 当遇到操作数的时候:
毫无疑问,直接输出
3 程序
#include <iostream>
#include <stack>
using namespace std;
void changePosfix();
int priorty(charch);
void main()
{
changePosfix();
}
void changePosfix()
{
stack<char>chStack;
charch;
bool bg= false;
while(ch = getchar() )
{
switch(ch)
{
case'(':
chStack.push(ch);
break;
case')':
while( chStack.top() != '(')
{
cout<<chStack.top();
chStack.pop();
}
chStack.pop();
break;
case'+':
case'-':
case'*':
case'/':
//for example a+b*c+d,when meet last
while( !chStack.empty() &&priorty(chStack.top() )>=priorty(ch) )
{
cout<<chStack.top();
chStack.pop();
}
// at last put ch in the end
chStack.push(ch);
break;
case'\n':
while( !chStack.empty() )
{
cout<<chStack.top();
chStack.pop();
}
bg = true;
break;
default:
cout<<ch;
}
if(bg )
break;
}
}
inline int priorty(char ch)
{
switch(ch)
{
case '+':
case '-':
return1;
case '*':
case'/':
return2;
default:
return0;
}
}