前缀、中缀、后缀表达式计算和转化算法详解

13 篇文章 0 订阅

前缀、中缀和后缀表达式

本页博客参考:https://www.cnblogs.com/zzliu/p/10801113.html、百度百科

概述

前缀、中缀、后缀表达式是对表达式的不同记法,其区别在于运算符相对于数字的位置不同,前缀表达式的运算符位于操作数之前,中缀和后缀同理

如:

中缀表达式:1 + (2 + 3) × 4 - 5
前缀表达式:- + 1 × + 2 3 4 5
后缀表达式:1 2 3 + 4 × + 5 -

中缀表达式是人们最常用的算术表示方法,人脑很容易理解,但对计算机来说很复杂,因为要判断计算的优先级太过繁琐。对计算机来说,计算前缀或后缀表达式的值非常简单

中缀转换为前缀、后缀

1+(2+3)*4-5为例

转为前缀:

先根据计算的优先级加上括号。

然后将运算符从优先级最低的括号移到该括号外,并删去括号

  1. ((1+((2+3)×4))-5)
  2. -(1+((2+3)×4))5
  3. -+1((2+3)×4)5
  4. -+1×(2+3)45
  5. -+1×+2345

或 先根据计算的优先级加上括号,然后将每个运算符移到其所在最内部的括号前面,最后一次性删除括号

  1. ((1+((2+3)×4))-5)
  2. -(+(1×(+(23)4))5)
  3. -+1×+2345

转为后缀:

同理,也是先加上括号,然后将运算符移动到其所在最内部的括号后面,删除括号

  1. ((1+((2+3)×4))-5)
  2. ((1((23)+4)×)+5)-
  3. 123+4×+5-

前中后缀在计算机中的计算与转换

前缀计算

  1. 从右至左扫描表达式
  2. 遇到数字时,将数字压栈,遇到运算符时,弹出栈顶的两个数,计算并将结果入栈
  3. 重复2直到表达式最左端,最后运算得出的值即为表达式的结果

例:
计算前缀表达式的值:- + 1 × + 2 3 4 5

  1. 从右至左扫描,将5,4,3,2压入堆栈;
  2. 遇到+运算符,弹出2和3(2为栈顶元素,3为次顶元素),计算2+3的值,得到5,将5压入栈;
  3. 遇到×运算符,弹出5和4,计算5×4的值,得到20,将20压入栈;
  4. 遇到1,将1压入栈;
  5. 遇到+运算符,弹出1和20,计算1+20的值,得到21,将21压入栈;
  6. 遇到-运算符,弹出21和5,计算21-5的值,得到16为最终结果

后缀计算

与前缀表达式类似,只是顺序是从左至右:

  1. 从左至右扫描表达式
  2. 遇到数字时,将数字压栈,遇到运算符时,弹出栈顶的两个数,计算并将结果入栈
  3. 重复2直到表达式最右端,最后运算得出的值即为表达式的结果

示例:
计算后缀表达式的值:1 2 3 + 4 × + 5 -

  1. 从左至右扫描,将1,2,3压入栈;
  2. 遇到+运算符,3和2弹出,计算2+3的值,得到5,将5压入栈;
  3. 遇到4,将4压入栈
  4. 遇到×运算符,弹出4和5,计算5×4的值,得到20,将20压入栈;
  5. 遇到+运算符,弹出20和1,计算1+20的值,得到21,将21压入栈;
  6. 遇到5,将5压入栈;
  7. 遇到-运算符,弹出5和21,计算21-5的值,得到16为最终结果
代码实现:点击查看

中缀转换为前缀(百度百科)

转换算法

(1) 首先构造一个运算符栈(也可放置括号),运算符(以括号为分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。

(2)从右至左扫描中缀表达式,从右边第一个字符开始判断:

如果当前字符是数字,则分析到数字串的结尾并将数字串直接输出。

如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将运算符直接入栈;否则将栈顶运算符出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。

如果是括号,则根据括号的方向进行处理。如果是向右的括号,则直接入栈;否则,遇向左的括号前将所有的运算符全部出栈并输出,遇右括号后将向左、向右的两括号一起出栈(并不输出)。

(3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。中缀表达式也就转换为前缀表达式了。

实例分析

中缀表达式“1+((2+3)*4)-5”转换为前缀表达式。

中缀表达式前缀表达式(栈尾)运算符栈(栈顶)说明
555,是数字串直接输出
-5--,栈内无运算符,直接入栈
5-)),直接入栈
45 4-)4,是数字串直接输出
*5 4-)**,栈顶是括号,直接入栈
)5 4- ) * )),直接入栈
35 4 3- ) * )3,是数字串直接输出
+5 4 3- ) * ) ++,栈顶是括号,直接入栈
25 4 3 2- ) * )+2,是数字串直接输出
(5 4 3 2+- ) *(,与栈里最后一个)抵消,并释放它们之间的+
(5 4 3 2+*-(,方法与上类同,请参考下一目录
+5 4 3 2+*-++,优先级大于等于栈顶运算符,直接入栈
15 4 3 2+*1-+1,是数字串直接输出
5 4 3 2+*1±扫描结束,将栈内剩余运算符全部出栈并输出
- + 1 * + 2 3 4 5逆缀输出字符串

中缀转换为后缀(百度百科)

算法实现

将一个普通的中缀表达式转换为逆波兰表达式的一般算法是:

首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为存放结果(逆波兰式)的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:

(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈。

(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符(不包括括号运算符)优先级高于S1栈栈顶运算符(包括左括号)优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符(包括左括号)低于(不包括等于)该运算符优先级时停止弹出运算符,最后将该运算符送入S1栈。

(3)若取出的字符是“(”,则直接送入S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。

(5)重复上面的1~4步,直至处理完所有的输入字符。

(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。

完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!

实例分析

下面以(a+b)*c为例子进行说明:

(a+b)c的逆波兰式为ab+c,假设计算机把ab+c按从左到右的顺序压入栈中,并且按照遇到运算符就把栈顶两个元素出栈,执行运算,得到的结果再入栈的原则来进行处理,那么ab+c的执行结果如下:

1)a入栈(0位置)

2)b入栈(1位置)

3)遇到运算符“+”,将a和b出栈,执行a+b的操作,得到结果d=a+b,再将d入栈(0位置)

4)c入栈(1位置)

5)遇到运算符“”,将d和c出栈,执行dc的操作,得到结果e,再将e入栈(0位置)

经过以上运算,计算机就可以得到(a+b)*c的运算结果e了。

代码实现:点击查看
  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前缀中缀后缀表达式是数学中常用的三种表示方式。它们在计算机中的应用主要是为了方便计算机进行表达式的求值。 1. 前缀表达式(也称为波兰表达式):运算符位于操作数之前。例如,前缀表达式"+ 2 3"表示的是2+3。 2. 中缀表达式:运算符位于操作数之间。例如,中缀表达式"2 + 3"表示的是2+3。 3. 后缀表达式(也称为逆波兰表达式):运算符位于操作数之后。例如,后缀表达式"2 3 +"表示的是2+3。 计算前缀中缀后缀表达式的方法略有不同: - 前缀表达式计算方法: 1. 从右到左扫描表达式。 2. 遇到数字时,将其压入栈中。 3. 遇到运算符时,从栈中弹出两个数字进行运算,并将结果压入栈中。 4. 重复上述步骤,直到表达式结束,栈中的数字即为表达式的结果。 - 后缀表达式计算方法: 1. 从左到右扫描表达式。 2. 遇到数字时,将其压入栈中。 3. 遇到运算符时,从栈中弹出两个数字进行运算,并将结果压入栈中。 4. 重复上述步骤,直到表达式结束,栈中的数字即为表达式的结果。 - 中缀表达式的计算方法: 1. 将中缀表达式转换为后缀表达式。 2. 使用后缀表达式计算方法计算结果。 下面是一个示例,演示了如何计算前缀中缀后缀表达式前缀表达式计算: ```python stack = [] expression = "+ 2 3" tokens = expression.split() for token in reversed(tokens): if token.isdigit(): stack.append(int(token)) else: operand1 = stack.pop() operand2 = stack.pop() if token == '+': stack.append(operand1 + operand2) elif token == '-': stack.append(operand1 - operand2) elif token == '*': stack.append(operand1 * operand2) elif token == '/': stack.append(operand1 / operand2) result = stack.pop() print("Result:", result) # 输出:5 ``` 后缀表达式计算: ```python stack = [] expression = "2 3 +" tokens = expression.split() for token in tokens: if token.isdigit(): stack.append(int(token)) else: operand2 = stack.pop() operand1 = stack.pop() if token == '+': stack.append(operand1 + operand2) elif token == '-': stack.append(operand1 - operand2) elif token == '*': stack.append(operand1 * operand2) elif token == '/': stack.append(operand1 / operand2) result = stack.pop() print("Result:", result) # 输出:5 ``` 中缀表达式转后缀表达式: ```python def infix_to_postfix(expression): precedence = {'+': 1, '-': 1, '*': 2, '/': 2} stack = [] postfix = [] tokens = expression.split() for token in tokens: if token.isdigit(): postfix.append(token) elif token == '(': stack.append(token) elif token == ')': while stack and stack[-1] != '(': postfix.append(stack.pop()) stack.pop() # 弹出左括号 else: while stack and stack[-1] != '(' and precedence[token] <= precedence.get(stack[-1], 0): postfix.append(stack.pop()) stack.append(token) while stack: postfix.append(stack.pop()) return ' '.join(postfix) expression = "2 + 3 * 4" postfix_expression = infix_to_postfix(expression) print("Postfix expression:", postfix_expression) # 输出:2 3 4 * + # 使用后缀表达式计算方法计算结果 stack = [] tokens = postfix_expression.split() for token in tokens: if token.isdigit(): stack.append(int(token)) else: operand2 = stack.pop() operand1 = stack.pop() if token == '+': stack.append(operand1 + operand2) elif token == '-': stack.append(operand1 - operand2) elif token == '*': stack.append(operand1 * operand2) elif token == '/': stack.append(operand1 / operand2) result = stack.pop() print("Result:", result) # 输出:14 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值