首先介绍下什么是中缀表达式,后缀表达式。
表达式一般分为前缀表达式,中缀表达式和后缀表达式。其中我们最为熟悉的是中缀表达式,也就是书本上最常用的表示形式。中缀表达式是将运算符放在两个操作数的中间。
前缀表达式是将运算符放在两个操作数之前。后缀表达式(又称逆波兰表达式)是将运算符放在两个操作数之后。例如:中缀表达式(A+(B-C/D)*E)对应的前缀表达式是(+A*-B/CDE)对应的后缀表达式为(ABCD/-E*+)。
由于后缀表达式即没有运算优先级又没有括号的约束问题,并且运算符的出现顺序正是实际计算的顺序,所以在计算机中计算一个后缀表达式的值要比计算一个中缀表达式的值简单的多。
简单的介绍下怎样阅读后缀表达式,或者说怎样变成我们熟悉的中缀表达式的形式。需要注意的两点是:1.在后缀表达式中运算符放在两个运算对象的后面。2.所有的计算按运算符出现的顺序。那么以上边的例子来讲,后缀表达式ABCD/-E*+。
1.首先进行的除法运算,运算对象为CD,转换为中缀表达式就是C/D。
2.第二个操作符是-,操作数是B和C/D(前面的操作部分以结果的形式看成一个整体),转化成中缀表达式就是B-C/D。
3.第三个操作符是*,操作数是B-C/D和E(注意算法的优先级,前面的操作数需要加括号),转化成中缀表达式是(B-C/D)*E。
4.第四个操作符是+,操作数是A和(B-C/D)*E,转化成中缀表达式就是A+(B-C/D)*E。结束。
下面详细介绍怎样将中缀表达式转化成后缀表达式(后缀表达式更利于计算机的计算)
我们发现中缀表达式与后缀表达式中操作数出现的顺序相同,不同的是运算符的先后顺序,所以转换的重点是运算符的处理上。首先设定运算符的优先级:
运算符 | (左括号 | +加,-减 | *乘,/除,%取模 | ^幂 |
优先级 | 0 | 1 | 2 | 3 |
上表中的数字代表优先级,数字越大表示优先级越高。
要想使运算符出现的顺序与真正的算数运算顺序相同,就要使优先级高的以及括号内的运算符出现在前面,在把中缀表达式转换成后缀表达式的时候要使用一个栈来保留还未送到后缀表达式的运算符,并称为运算符栈(利用了栈先入后出的特性)。实现转换的基本步骤如下:
1.初始化一个运算符栈。
2.从算数表达式输入的字符串中依次从左向右每次读取一个字符。
3.如果当前字符是操作数,则直接填写到后缀表达式。
4.如果当前字符是(左括号,将其压入运算符栈(第一步定义)。
5.如果当前字符为运算符,则
5.1.当运算符栈为空,则将其压入运算符栈。
5.2.当此运算符的优先级高于栈顶元素的时候,则将此运算符压入运算符栈;否则,弹出栈顶运算符到后缀表达式,并且将当前运算符压栈。回到步骤2.
6.如果当前字符是)右括号,反复将栈顶元素弹出到后缀表达式,直到栈顶元素是左括号(为止,并将左括号从栈中弹出丢弃。
7.如果读取还未完成,回到步骤2.
8.如果读取完成,则将栈中剩余的运算符依次弹出到后缀表达式。
为了方便大家理解,下面使用前面的例子看由A+(B-C/D)*E如何得到后缀表达式ABCD/-E*+的。
1.初始化一个运算符栈,不妨用st表示。
2.读取一个字符,‘A',为操作数,直接送到后缀表达式,当前后缀表达式为A。
3.读取下一个字符,‘+’,为操作符,且运算符栈为空,压入操作符栈。当前操作符栈为+,后缀表达式为A。
4.读取下一个字符,‘(’,为左括号,将其压入操作符栈。当前操作符栈为(+,后缀表达式为A。
5.读取下一个字符,‘B’,为操作数,直接送到后缀表达式,当前后缀表达式为AB。
6. 读取下一个字符,‘-’,为操作符,且优先级高于栈顶元素,压入操作符栈。当前操作符栈为-(+,后缀表达式为AB。
7. 读取一个字符,‘C',为操作数,直接送到后缀表达式,当前后缀表达式为ABC。
8. 读取下一个字符,‘/’,为操作符,且优先级高于栈顶元素,压入操作符栈。当前操作符栈为/-(+,后缀表达式为ABC。
9. 读取一个字符,‘D',为操作数,直接送到后缀表达式,当前后缀表达式为ABCD。
10. 读取下一个字符,‘)’,为右括号,反复将栈顶元素弹出到后缀表达式,直到栈顶元素是左括号(为止,并将左括号从栈中弹出丢弃。当前操作符栈为+,后缀表达式为ABCD/-。
11. 读取下一个字符,‘*’,为操作符,且优先级高于栈顶元素,压入操作符栈。当前操作符栈为*+,后缀表达式为ABCD/- 。
12. 读取一个字符,‘E',为操作数,直接送到后缀表达式,当前后缀表达式为ABCD/- E。
13. 读取完毕,将栈中剩余的所有运算符弹出到后缀表达式,操作符栈置空,后缀表达式为ABCD/- E*+。
转换完成!!!