标准的表达式,在数学上称为中缀表达式,其运算符在两个操作数的中间,例如:a*b+(c-d/e)*f。中缀表达式是人们常用的算数表示方法,但它不容易被计算机解析,因为要先判断有无括号,再根据运算符的优先级运算,这是很麻烦的。
于是,波兰数学家Jan Lukasiewicz发明了波兰表示法和逆波兰表示法,即前缀表达式和后缀表达式。前缀表达式的运算符在两个操作数之前,例如:+*ab*-c/def,运算规则为,连续出现的两个操作数和它们之前且紧靠它们的运算符构成一个最小表达式;后缀表达式的运算符则紧跟在两个操作数之后,例:ab*cde/-f*+,运算规则为:每个运算符和在它之前出现且紧靠它的两个操作数构成一个最小表达式。这两种表达式的最大特点是不需要括号来表明优先级,经常用于计算机科学,特别是编译器设计方面。
后缀表达式的求值规则为:从左到右扫描后缀表达式,如果遇到操作数,将其压入栈中,如果遇到操作符,则从栈中弹出两个操作数,计算结果,然后把结果入栈,直到遍历完后缀表达式,则计算完成,此时的栈顶元素即为计算结果。
如上的后缀表达式求值过程为:
(1) 初始化栈,栈顶指针为空;
(2) 遇到操作数a,入栈;
(3) 遇到操作数b,入栈;
(4) 遇到操作符*,弹出栈中两个元素,计算结果入栈;
(5) 遇到操作数c,入栈;
(6) 遇到操作符d,入栈;
(7) 遇到操作数e,入栈;
(8) 遇到运算符/,弹出栈中两个元素,计算结果入栈;
(9) 遇到操作符-,弹出栈中两个元素,计算结果入栈;
(10) 遇到操作数f,入栈;
(11) 遇到操作符*,弹出栈中两个元素,计算结果入栈;
(12) 遇到操作符+,弹出栈中两个元素,计算结果入栈;
C++实现代码如下:(虽说是C++实现,但里面不少都是用C来完成的)
注:输入的后缀表达式每个元素要用空格分开,便于区分不同的数
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct Node{
float date;
Node *next;
};
class Stack{
private:
Node *top;
public:
Stack()
{
top=NULL;
}
~Stack();
void Push(float Elem);//入栈
float Pop();//出栈
float Top();//栈顶元素
bool Empty()
{
return (top==NULL);
}
};
Stack::~Stack()
{
Node *p;
while (top)
{
p=top->next;
delete top;
top=p;
}
cout<<"栈已清空"<<endl;
}
float Stack::Pop()
{
if (top==NULL)
{
cout<<"栈空"<<endl;
return -1;
}
Node *p;
float temp;
temp=top->date;
p=top;
top=top->next;
delete p;
return temp;
}
void Stack::Push(float Elem)
{
Node *s;
s=new Node;
s->date=Elem;
s->next=top;
top=s;
}
float Stack::Top()
{
return top->date;
}
int main()
{
Stack st;
char ch;
//两次取出栈顶元素,放入num1,num2中,sum为它俩的运算结果
float num1,num2,sum;
char buffer[10];//缓冲区,存放操作数
int i=0;
cout<<"请输入后缀表达式:(用空格隔开,以#为结束标志)"<<endl;
scanf("%c",&ch);
while (ch!='#')
{
while ((ch>='0'&&ch<='9')||ch=='.')//0~9间的数字或小数点存入缓存数组中
{
buffer[i]=ch;
i++;
buffer[i]='\0';//让数组最后一位元素为‘\0',构成字符串,调用atof函数
scanf("%c",&ch);
if (ch==' ')//如果读取到空格,说明已读取完一个操作数
{
float temp=atof(buffer);//把字符串转为浮点数
st.Push(temp);//进栈
i=0;//重置零
break;//读取了一个数后跳出循环重新判断
}
}
if (ch=='+'||ch=='-'||ch=='*'||ch=='/')//如果ch是运算符
{
num1=st.Pop();//取出两个栈顶元素
num2=st.Pop();
//后取出的那个数在运算符前
switch(ch)
{
case '+':
sum=num2+num1;
st.Push(sum);
break;
case '-':
sum=num2-num1;
st.Push(sum);
break;
case '*':
sum=num1*num2;
st.Push(sum);
break;
case '/':
sum=num2/num1;
st.Push(sum);
break;
}
}
scanf("%c",&ch);
}
cout<<st.Pop()<<endl;
return 0;
}
运行结果如下: