标签:文法 方式 中序遍历 while 执行 扫描 表示 条件 应用
逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。
中缀表达式就是我们最熟悉的一种表达式:1+2,3(3+4),1+23+6,...等都是中缀表示法。对于人们来说,也是最直观的一种求值方式,先算括号里的,
然后算乘除,最后算加减,但是,计算机处理中缀表达式却并不方便,故引出了前缀和后缀。中缀表达式得名于它是由相应的语法树的中序遍历的结果得到的。
前缀表达式又叫做波兰式。同样的道理,表达式的前缀表达式是由相应的语法树的前序遍历的结果得到的。
如1 + 2 * (3 - 4) - 5 * 6
的前缀表达式为- + 1 * 2 - 3 4 * 5 6
由前缀表达式求出结果有下面两种思路:
- + 1 * 2 - 3 4 * 4 5
,扫描到- 3 4
时,会计算3 - 4 = -1
,表达式变成:- + 1 * 2 -1 * 5 6
继续扫描到* 2 -1
,计算2 * -1 = -2
,表达式变成:- + 1 -2 * 5 6
,继续+ 1 -2
,依此类推。后缀表达式又叫做逆波兰式。它是由相应的语法树的后序遍历的结果得到的。如1 + 2 * (3 - 4) - 5 * 6
的后缀表达式为:1 2 3 4 - * + 5 6 * -
注意:逆波兰记法并不是简单的波兰表达式的反转。因为对于不满足交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法“/ 6 3”的逆波兰记法是“6 3 /”而不是“3 6 /”;数字的数位写法也是常规顺序。
由前缀表达式求出结果十分方便,只需要用一个栈S实现:
既然中缀表达式对于计算机的运算并不便利,而前缀后缀表达式的计算相对简单方便。因此,找到一种途径将中缀表达式转换成前缀后缀表达式就十分重要。实际上,二者的转换算法看起来也很像一个逆过程。因此,我们着重讨论中缀转后缀。
从理论上讲,已知一棵二叉树的中序遍历序列,要求出它的后序遍历序列是不唯一的,即文法是有多义性的。所以,在这里我们要加上优先级这一限制条件,转换就变得唯一了。
PROCESS BEGIN:
1.从左往右扫描中缀表达式串s,对于每一个操作数或操作符,执行以下操作;
2.IF (扫描到的s[i]是操作数DATA)
将s[i]添加到输出串中;
3.IF (扫描到的s[i]是开括号‘(‘)
将s[i]压栈;
4.WHILE (扫描到的s[i]是操作符OP)
IF (栈为空 或 栈顶为‘(‘ 或 扫描到的操作符优先级比栈顶操作符高)
将s[i]压栈;
BREAK;
ELSE
出栈至输出串中
5.IF (扫描到的s[i]是闭括号‘)‘)
栈中运算符逐个出栈并输出,直到遇到开括号‘(‘;
开括号‘(‘出栈并丢弃;
6.返回第1步
7.WHILE (扫描结束而栈中还有操作符)
操作符出栈并加到输出串中
PROCESS END
中缀表达式5 + ((1 + 2) * 4) - 3
写作转换成后缀表达式:5 1 2 + 4 * + 3 -
下表给出了该逆波兰表达式从左至右求值的过程,堆栈栏给出了中间值,用于跟踪算法。
输入 | 操作 | 堆栈 | 注释 |
---|---|---|---|
5 | 入栈 | 5 | |
1 | 入栈 | 5, 1 | |
2 | 入栈 | 5, 1, 2 | |
+ | 加法运算 | 5, 3 | 1, 2出栈,将结果3入栈 |
4 | 入栈 | 5, 3, 4 | |
* | 乘法运算 | 5, 12 | 3, 4出栈,将结果12入栈 |
+ | 加法运算 | 17 | 5, 12出栈,将结果17入栈 |
3 | 入栈 | 17, 3 | |
- | 减法运算 | 14 | 17, 3出栈,将结果14入栈 |
计算完成时,栈内只有一个操作数,这就是表达式的结果:14
。
上述运算可以重写为如下运算链方法:1 2 + 4 * 5 + 3 -
中缀表达式转换成前缀表达式和中缀表达式转换成后缀表达式十分类似,只需要将扫描方向由前往后变成由后往前,将(
改为)
,)
改为(
。
具体的应用可以见我的另外一篇博客:基于逆波兰表达式实现图形化混合计算器.
标签:文法 方式 中序遍历 while 执行 扫描 表示 条件 应用
原文地址:https://www.cnblogs.com/lzyws739307453/p/12907662.html