中缀表达式是我们平常看到的算数表达式
如:a+b*(c-d)
而后缀表达式则是将计算数和计算符分开写,其中每个操作符与对应的两个操作数的位置关系是两个操作数在前而操作符在后。
如上面的例子中的中缀表达式可以转化为后缀表达式:abcd-*+
转化算法为:
(1)若遇到操作数,则直接将其输出
(2)若遇到操作符,则我们将其放入栈中,遇到'('时也将其放入栈中
(3)若遇到')',则循环弹出栈中的元素,直到弹出的操作符为'('为止。这时左括号只弹出而并不输出
(4)若遇到其他操作符,则先应该判断栈顶操作符的优先级是否小于遇到的操作符,或者操作栈为空,否则应该先循环弹出比遇到的操作符优先级高或相等的的操作符,再将遇到的操作符压栈。注意一个细节,若此步栈顶元素时左括号时,则直接将遇到的操作符压栈,而不是弹出左括号。
(5)若读到了输入的末尾,此时操作栈内依然有操作符则将剩余操作符依次弹出
下面给出代码实现:(栈的数据结构是我手写的,可使用STL中的Stack库)
#include<iostream>
using namespace std;
template<class T>
class Stack
{
private:
int top;
T *elements;
int MaxSize;
public:
Stack(int Maxsize);
~Stack(){
delete []elements;
}
int push(const T& x);
int size();
T pop();
T gettop();
void MakeEmpty(){
top=-1;
}
bool empty(){
return top==-1;
}
bool full(){
return top==MaxSize-1;
}
};
template<class T>
int Stack<T>::size()
{
return top+1;
}
template<class T>
Stack<T>::Stack(int Maxsize)
{
top=-1;
elements=new T[MaxSize];
MaxSize=Maxsize;
}
template<class T>
int Stack<T>::push(const T& x)
{
if(!full()){
elements[++top]=x;
return 0;
}
return -1;
}
template<class T>
T Stack<T>::pop()
{
return elements[top--];
}
template<class T>
T Stack<T>::gettop()
{
return elements[top];
}
int rnk(char x)
{
if(x=='*'|| x=='/')return 2;
if(x=='+'|| x=='-')return 1;
if(x=='(')return 0;
else return -1;
}
int isoperator(char x)//判断一个字符是否为操作符;
{
if(x=='+'||x=='-'||x=='*'||x=='/'||x=='('||x==')')return 1;
else return 0;
}
int main()
{
Stack<char> ins(100);//存放操作符的栈;
char exp[100];//中缀表达式;
char res[200];//存放后缀表达式;
int i=0;
cin.getline(exp,100);//使用getline防止输入空格时cin无法读取全部表达式;
for(int k=0;exp[k]!='\0';k++)
{
int a=ins.size();
if(exp[k]==' ')continue;//防止误输入空格;
if(!isoperator(exp[k]))
{
res[i++]=exp[k];
continue;
}
else
{
if(ins.empty()){
ins.push(exp[k]);
continue;
}
if(exp[k]=='(')
{
ins.push(exp[k]);
continue;
}
if(exp[k]==')')
{
while(ins.gettop()!='(')
{
res[i++]=ins.pop();
}
ins.pop();//去除'(';
continue;
}
else
{
while((rnk(ins.gettop())>=rnk(exp[k]))&&!ins.empty())
{
res[i++]=ins.pop();
}
ins.push(exp[k]);
}
}
}
while(ins.size()!=0)
{
res[i++]=ins.pop();
}
for(int j=0;j<i;j++)
{
cout<<res[j];
}
}