栈经典问题之前缀、中缀、后缀表达式

定义

中缀表达式是一个通用的算术逻辑表示法,是最常见的一种表达式,如5*(2+3)-4;

前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面,如上述表达式的前缀表示为- * 5 + 2 3 4

后缀表达式不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行,上述表达式的后缀表示为5 2 3 + * 4 -

中缀、前缀、后缀表达式分别对应着二叉树的中序、前序、后序遍历,如何通过中缀表达式建立二叉树呢?可以参考这里:http://blog.csdn.net/wzy_1988/article/details/11179281,这里就不做过多叙述,至于如何用代码来实现,后续二叉树的文章中会有介绍,先挖个坑。

如何计算值前缀、后缀、中缀表达式

首先需要明确的一点是,对于人来说,中缀表达式是很好计算的,而对于计算机来说,前缀表达式和后缀表达式更好计算值。

计算前缀表达式
如前所述的前缀表达式- * 5 + 2 3 4,从右到左扫描,如果遇到操作数则进栈,如果遇到运算符,则弹出两个栈顶元素进行运算,并将结果入栈,直到扫描结束:
(1)将4 3 2 分别入栈
(2)将2 3出栈,2+3=5,将结果5入栈
(3)将5入栈
(4)将5 5出栈,5*5=25,将结果25入栈
(5)将25 4出栈,25-4=21,即21,为最终结果
注意:运算时第一个出栈元素放在运算符的左边第二个放在右边

计算后缀表达式
后缀表达式的计算与前缀表达式相似,从左到右扫描,如果遇到操作数则进栈,如果遇到运算符,则弹出两个栈顶元素进行运算,并将结果入栈,直到扫描结束,后缀表达式5 2 3 + * 4 -的计算过程如下:
(1)将5 2 3进栈
(2)将3 2出栈,2+3=5,将结果5入栈
(3)将5 5出栈,5*5=25,将25入栈
(4)将4进栈
(5)将4 25出栈,25-4=21,即得到结果
注意:运算时第一个出栈元素放在运算符的右边第二个放在左边

计算中缀表达式
定义两个栈,operatorStack放运算符,operandStack放操作数,从左到右扫描中缀表达式:
(1)如果是操作数,则进栈
(2)如果是运算符
(2.1)如果是左括号或operatorStack栈为空或栈顶运算符为左括号,进栈
(2.2)如果是右括号,两个栈顶操作数出栈,栈顶运算符出栈,将计算结果进栈,直到出栈的运算符是左括号为止
(2.3)如果是其他情况,判断与栈顶运算的优先级,如果大于栈顶运算符,则进栈;如果小于,两个栈顶操作数出栈,栈顶运算符出栈,将计算结果进栈,最后将该运算符进栈
(3)扫描完成,判断运算符栈是否为空,不为空则不断弹出两个操作数和一个运算符,将结果入栈,直到运算符栈为空
(4)操作数栈中剩下的一个数即为结果
下面以计算5*(2+3)-4为例:
这里写图片描述

中缀转后缀

步骤:
(1)创建一个栈存放运算符,用String类对象postfix将结果拼接起来。
(2)从左到右扫描中缀表达式
(3)如果是操作数,拼接到postfix
  (3.1)如果是左括号或栈为空,直接进栈
  (3.2)如果是右括号,栈顶元素出栈,拼接到postfix,直到左括号出栈,但左括号不输出
  (3.3)如果是其他运算符,比较与栈顶运算符的优先级,如果大于,进栈,如果小于或等于,栈顶元素出栈并拼接到postfix,将该运算符进栈
(4)扫描完成后,将栈中是运算符全部拼接的str
下面以5*(2+3)-4为例:
这里写图片描述

中缀转前缀

与中缀转后缀相似,不同点在于因为要从右到左扫描,先遇到的是右括号。而且最后拼接的结果与预期结果正好相反,因此需要另一个栈result存放中间结果,还有一个不同点在于比较运算符的优先级时,相同优先级也要进栈,步骤如下:
(1)创建一个栈存放运算符,创建一个result栈存放中间结果
(2)从右到左扫描中缀表达式
(3)如果是操作数,压入result栈
  (3.1)如果是右括号或栈为空,直接进运算符栈
  (3.2)如果是左括号,栈顶元素出栈,压入result栈,直到右括号出栈,但右括号不输出
  (3.3)如果是其他运算符,比较与栈顶运算符的优先级,如果大于或等于,进栈,如果小于,栈顶元素出栈并压入result栈,然后该运算符压入运算符栈
(4)扫描完成后,将运算符栈中的剩余元素压入result栈
下面以5*(2+3)-4为例:
这里写图片描述

下面是所有代码:

public class Calculator {
    /**
     * 1、包含计算前缀、后缀、中缀表达式的方法
     * 2、包含中缀转前缀、中缀转后缀的方法
     * 3、包含一些辅助操作,如计算运算符的优先级、获取操作数等
     * 4、注意,如果直接输入前缀表达式或后缀表达式,每一项之间用空格分开,
     *    否则无法计算含有两位及以上的操作数的表达式,因为不知道哪几个数字组成一个数
     * 5、本例中使用的栈为自定义栈,也可以用java提供的位于java.util包下的Stack
     * 6、为减少代码并方便测试,将三个成员变
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值