四则运算表达式求值:
20世纪50年代波兰逻辑学家janlukasiewicz想到了一种不需要括号的后缀表达式法,可以称为逆波兰表示(RPN).reverse polish notation .
这种后缀表示法,是表达式的一种新的显示方式,非常巧妙的解决了程序实现四则运算的难题。
举个例子:“9+(3-1)*3+10/2”应该是 9 3 1-3*+10/+,这样的表达式称为后缀表达式。叫后缀的原因在于所有的符号都要出现在运算数字的后面。显然这里是没有括号的。对于从来没有接触过后缀表达式,我们很难理解这样的表示的具体含义是什么。
其实这里的规则是:
从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号就将栈顶的两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。
|
|
1 |
3 |
9 |
遇到减号,1,3出栈(3-1)将结果重新入栈
|
|
|
(3-1) |
9 |
当然这里不可能在栈里存放着(3-1),只能是2,这里姑且这么写。
然后遇到3,进栈,
|
|
3 |
(3-1) |
9 |
遇到*,3和(3-1)出栈,变成(3-1)*3,将该结果再进栈,变成
|
|
|
(3-1)*3 |
9 |
然后遇到的是加好,数据出栈,9+(3-1)*3,然后将该结果入栈,这里是15,直接将15入栈,同时下面数据遍历到10,2也入栈
|
|
2 |
10 |
15 |
,遍历继续,到/号,出栈栈顶两个数据元素:10/2,结果入栈,变成
|
|
|
5 |
15 |
最后遍历+,栈顶两个数据元素出栈15+5 =20 ,为最终的结果,是符合计算机的运算方式的。
但是这种后缀表达式法是如何得到结果的呢?
这里在介绍一个概念,我们平时所用到的四则运算表达式,如 9+(3-1)*3+10/2,这种方式叫做中缀表达式。因为所有的运算符号都在两个数字中间。
这里的从中缀表达式到后缀表达式的规则是:
从左到右遍历中缀表达式,遇到数字就输出,(可以作为后缀表达式的一部分);若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号,则栈顶元素一次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式位置。过程如下:
|
|
|
|
+ |
输出9,然后+号入栈,如上
左括号入栈,并继续输出3,
|
|
|
( |
+ |
输出: 9 3
减号优先级和加好相同,进栈
|
|
- |
( |
+ |
输出9 3 1,同时右括号入栈
|
) |
- |
( |
+ |
两个括号匹配,他们之间出栈,输出中是没有括号的,因此,输出如下:
9 3 1-,栈变为
|
|
|
|
+ |
接着是*,因为栈顶元素为+,加号的优先级要低于*,因此不出栈,*进栈
|
|
|
* |
+ |
输出为9 3 1-3,下面是符号+,将要进栈,这里因为栈顶符号为*,比+的优先级要高,所以,*出栈,并且栈中余下的符号也出栈,同时这里的+入栈,
|
|
|
|
+ |
输出:9 3 1 -3 *+10,/要入栈,而且栈顶元素是加号,优先级低,/入栈,
|
|
|
/ |
+ |
这里的输出是:9 3 1 -3*+10 2 ,最终中缀表达式结束了,将栈中余下的符号弹出,最终的后缀表达式是:9 3 1 -3*+10 2 /+
这里还有一种叫做是前缀表达式,不过这里由中缀表达式转化为前缀表达式有点复杂。但是前缀表达式转化为中缀表达式的规则确实和后缀表达式的类似,不过是从前缀表达式的后面开始,遇到数字进栈,遇到符号则弹出栈顶两个元素,并将结果重新入栈,如此从前遍历。
具体可以参考:http://blog.csdn.net/antineutrino/article/details/6763722