四则运算--语法树、中缀表达式、波兰表达式、逆波兰表达式

中缀表达式和语法树

中缀表达式

类最熟悉的一种表达式1+2,(1+2)3,3+42+4等等都是中缀表示法。对于人们来说,也是最直观的一种求值方式,先算括号里的,然后算乘除,最后算加减,但是,计算机处理中缀表达式却并不方便,因为没有一种简单的数据结构可以方便从一个表达式中间抽出一部分算完结果,再放进去,然后继续后面的计算(链表也许可以,但是,代价也是不菲)。
注意到中缀表达式是含有括号的,是我们数学中使用的表达式

语法树

在介绍前缀,后缀表达式之前,我想先通过我们最熟悉的中缀表达式画出一棵语法树来直观认识前后缀表达式。以A+B*(C-D)-EF为例:
在这里插入图片描述
如何从 中缀表达式A+B
(C-D)-E*F得到上述的语法树呢?过程是这样的:
(1)从当前的中缀表达式中选择最后执行的四则运算符,作为当前的根节点,若没有运算符,将数字写在对应的节点处
(2)该运算符将中缀表达式分为左右两部分,即为左右子树,重复步骤(1);
中缀表达式就是该语法树的中序遍历得到(添加必要的括号)

前缀表达式(波兰式)

前缀表达式又叫做波兰式。同样的道理,表达式的前缀表达式是由相应的语法树的前序遍历的结果得到的。
上图的前缀表达式为- + A * B - C D * E F,

中缀表达式生成前缀表达式

中缀表达式生成前缀表达式,需要借助一个,需要从尾部开始扫描前缀表达式,同时可以使用一个vector<string>或者queue<string>或者list<string>等容器保留前缀表达时,注意最后生成的表达式容器需要翻转后,才是正确的中缀表达式,步骤如下:
(1)扫描到操作数,无条件归入前缀表达式容器
(2)遇到右括号“(”,无条件入辅助栈;
(3)遇到左括号")",一定不入栈不归入前缀表达式,并且将栈中的元素一次弹出归入前缀表达式,直到弹出右括号")”,并且将右括号抛弃
(4)如果遇到操作符,需要比较优先级,如果当前的操作符的优先级
大于等于
栈顶的操作符,直接当前操作符压入栈中,如果当前操作符的优先级小于栈顶操作符的优先级,将栈顶的操作符出栈,并归入到前缀表达式中,直到当前操作符的优先级大于或等于栈顶操作符的优先级,将当前操作符压入栈中
(5)直到扫描完所有的中缀表达式
(6)将栈中的元素全部归入前缀表达式中
(7)将前缀表达式翻转后就是最后的结果

根据前缀表达式计算结果

前缀表达式计算结果,需要从尾部开始扫描入,核心思想就是**“弹出两个数压入一个数”–也就是弹出两个操作数,计算后将结果压入栈**。注意:数字无条件入栈,操作符无条件出栈操作。(注意:先弹出的是右操作数,后弹出的是左操作数)
步骤如下:
(1)扫描到操作数,则压入栈
(2)扫描到操作符,弹出栈中的两个数字,计算后将结果压入栈;
(3)循环上面的操作,直到扫描到尽头
注意:波兰表达式的形式不同需要不同的处理,因为数字可能含有多位,如果表达式是vector<string>,那么可以直接扫描,如果只是一个string,那么需要自己处理数字。
这里我们使用vector<string>

//波兰表达式,求结果
//基本四则运算
 int cal(string op,int a,int b)
 {
   
        int res = 0;
        if(op=="+") res = a+b;
        else if(op=="-") res = a-b;
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值