一、栈的表达式
栈的三种表达式分别是:前缀、中缀和后缀。
注意事项:栈顶元素是最后被插入和最早被删除的元素。
二、前缀表达式
前缀表达式也称波兰表达式,就是所有运算符都在操作数前面。它的求值过程:计算机从右往左扫描,遇到数字就把数字压入数栈;遇到符号,就弹出数栈中的栈顶和次顶的两个数字和符号进行运算,把计算的结果压入栈中。
例: (3+4)*5-2的前缀表达式为 - * + 3 4 5 2
- 从右往左扫描,把数字2 5 4 3依次压入数栈;
- 遇到符号 + ,就弹出数栈中栈顶和次顶的两个数字(3、4)和符号(+)进行运算 ====> 3+4=7; 7压入栈中,数栈:7 5 2
- 继续向左扫描,遇到*,弹出7和5运算,7*5=35, 压入栈中。 35 2
- 遇到符号 - ,弹出35和2运算,35-2=33 。
三、中缀表达式
中缀表达式就是常见的运算表达式,需要比较运算符的优先级,对于人脑来说比较好比较,但是对于计算机来说是比较难算的。
四、后缀表达式
后缀表达式又叫逆波兰表达式,就是运算符在操作数后面。
例如(3+4)*5-2的后缀表达式为3 4 + 5 *2- , 计算机从左往右扫描, 遇到数字3和4,将数字3和4压入数栈,继续扫描。遇到符号+,就弹出数栈中栈顶和次顶的两个数字和符号进行运算 ===> 4+3 = 7; 7压入栈中,数栈 7 ;继续扫描遇到数字5,压入栈中,数栈5 7;继续扫描遇到*,弹出7、5进行运算,7*5=35;数栈35;继续扫描遇到2压入数栈,数栈2 35;继续遇到-,弹出35和2进行运算 ===> 35-2 =33。
五、带括号的中缀表达式的转换(详细步骤配图)
把带括号的中缀表达式转换为后缀表达式:9/(3+2)-6*(3-2)
转换规则:
首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为存放结果(逆波兰式)的栈S2(空栈),S1栈可先放入优先级最低的运算符#,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是操作数 ( 9, 3,2,6,3,2 ),则分析出完整的运算数,该操作数直接送入S2栈。
(2)若取出的字符是运算符 ( * / - +),则将该运算符与S1栈栈顶元素比较,如果该运算符(不包括括号运算符)优先级高于S1栈栈顶运算符(包括左括号)优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符(包括左括号)低于(不包括等于)该运算符优先级时停止弹出运算符,最后将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入S1栈顶。
(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符。
(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。
如果表达式结束,但栈中还有元素,将所有元素出栈,添加到后缀表达式中。
例如:9/(3+2)-6*(3-2)
1、分配两个栈,s1栈可放入#(优先级最低的运算符),s2栈暂时为空。
2、从左往右扫描,遇见操作数9,直接送入栈,如下图(左为s1,右为s2)
3、 继续扫描,遇见/,且其优先级比#高,则送入s1栈。
4、 继续扫描,遇见(,直接送入s1栈。
5、继续扫描,操作数3直接入s2栈。
6、 继续扫描,+与s1栈顶元素(比较,+优先级高,把+送入s1栈。
7、 继续扫描,操作数2直接入s2栈。
8、 继续扫描遇),将距离s1栈栈顶最近的至”(”之间的运算符逐个出栈,依次送入s2栈,”(”不需要送入。
9、 继续扫描至 - ,与/比较,比/运算优先级低,将s1的栈顶元素入s2栈。
10、继续扫描至6,入s2栈。
11、 继续扫描遇 *,与s1栈顶运算符比,*高,压入s1栈。
12、 继续扫描遇(,入s1栈。
13、 继续扫描至3,入s2栈。
14、 继续扫描遇- ,与s1栈顶运算符比,-高,压入s1栈。
15、 继续扫描,操作数2入s2栈。
16、 继续遇),将距离s1栈栈顶最近的至”(”之间的运算符逐个出栈,依次送入s2栈,”(”不需要送入。
17、 表达式结束但s1栈中还有元素,将所有元素取出添加到s2中。
所以,9/(3+2)-6*(3-2)的后缀表达式为932+/632-*-
学习日志如有错误,还望指正,多谢!