首页 > 其他分享 >算术表达式求值法(表达式求值)之后序表示法求值

算术表达式求值法(表达式求值)之后序表示法求值

时间:2023-09-27 22:46:30浏览次数:33  
标签:表示法 operator token 操作符 求值 stack 表达式

概念

后序表示法(Postfix Notation)又称为逆波兰表示法(Reverse Polish Notation,RPN),是一种用于表示数学表达式的方法,其中运算符位于它们的操作数之后。

这种表示法非常适合用栈来计算表达式的值,因为它消除了括号的需求,使计算机能够轻松地理解和求解表达式。

例如,表达式 "3 + 4" 在后序表示法中表示为 "3 4 +"。后序表示法对于计算表达式非常有用,因为它无需括

 

后序表示法的计算步骤

  1. 创建一个空栈,用于存储操作数。
  2. 从左到右遍历后序表达式中的每个元素。
  3. 如果遇到操作数(数字),将其推入栈中。
  4. 如果遇到操作符(+、-、*、/等),则从栈中弹出两个操作数,执行相应的操作,然后将结果推回栈中。
  5. 继续遍历表达式,重复步骤3和步骤4,直到处理完整个表达式。
  6. 最终,栈中将只剩下一个值,这个值就是表达式的结果。

示例

 1 def evaluate_postfix(expression):
 2     stack = []  # 用于存放操作数
 3     operators = set(['+', '-', '*', '/'])
 4 
 5     for token in expression.split():
 6         if token not in operators:
 7             # 如果是操作数,将其压入栈
 8             stack.append(float(token))
 9         else:
10             # 如果是操作符,弹出栈顶的两个操作数,并执行相应的操作
11             operand2 = stack.pop()
12             operand1 = stack.pop()
13 
14             if token == '+':
15                 result = operand1 + operand2
16             elif token == '-':
17                 result = operand1 - operand2
18             elif token == '*':
19                 result = operand1 * operand2
20             elif token == '/':
21                 result = operand1 / operand2
22 
23             # 将结果压入栈
24             stack.append(result)
25 
26     # 最终栈中剩下的元素即为表达式的结果
27     return stack[0]
28 
29 
30 # 后续表示法表达式
31 expression = "3 4 + 2 * 7 /"
32 result = evaluate_postfix(expression)
33 print("后序表达式的结果:", result)   # 后序表达式的结果: 2.0

输出结果:

后序表达式的结果: 2.0

  

 

最佳实践和注意事项

  1. 确保后序表达式的格式正确,每个元素之间使用空格分隔。
  2. 对于操作符,确保在计算之前检查栈是否有足够的操作数。
  3. 如果表达式中包含负数,可以使用单独的字符来表示,例如"5 -3 +"表示5 - (-3)。
  4. 考虑添加错误处理机制,以处理不合法的表达式或除零错误。

中序表示法转后续表示

 1 # 中序表示法转后续表示法
 2 def infix_to_postfix(infix_expression):
 3     precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}  # value越大,key的优先级越大
 4     output = []  # 输出列表
 5     operator_stack = []  # 操作符栈
 6 
 7     # 判断优先级:当前操作符与栈顶操作符
 8     def has_higher_precedence(op1, op2):
 9         return precedence[op1] >= precedence[op2]
10 
11     for token in infix_expression.split():
12         if token.isnumeric():
13             output.append(token)
14         elif token in precedence:
15             while (operator_stack and operator_stack[-1] != '(' and
16                    has_higher_precedence(operator_stack[-1], token)):   # 栈顶优先级高,则出栈
17                 output.append(operator_stack.pop())
18             operator_stack.append(token)
19         elif token == '(':  # 直接入栈
20             operator_stack.append(token)
21         elif token == ')':  # 直接出栈,一直到(
22             while operator_stack and operator_stack[-1] != '(':
23                 output.append(operator_stack.pop())
24             if operator_stack and operator_stack[-1] == '(':  # (出栈
25                 operator_stack.pop()
26 
27     while operator_stack:  # 不为空,则出栈
28         output.append(operator_stack.pop())
29 
30     return ' '.join(output)   # 拼接后续表达式:其实操作数顺序从左向右排序,操作符的顺序是按照优先级来的。
31 
32 
33 # 中序表示法示例
34 infix_expression = "3 + 4 * ( 2 - 1 ) / 5"
35 postfix_expression = infix_to_postfix(infix_expression)
36 print("中序表达式:", infix_expression)     # 中序表达式: 3 + 4 * ( 2 - 1 ) / 5
37 print("后序表达式:", postfix_expression)   # 后序表达式: 3 4 2 1 - * 5 / +

定义了一个infix_to_postfix函数,它接受一个中序表达式作为输入并返回后序表达式。该函数使用了一个输出列表output和一个操作符栈operator_stack来完成转换。

主要思路是遍历中序表达式的每个元素,根据运算符的优先级和括号来决定操作符的入栈和出栈。具体步骤如下:

  1. 如果遇到操作数(数字),直接添加到输出列表中。
  2. 如果遇到操作符,根据其优先级和栈顶操作符的优先级来决定是否出栈,并将当前操作符入栈。
  3. 如果遇到左括号(,直接入栈。
  4. 如果遇到右括号),将操作符栈中的操作符出栈直到遇到左括号,并将左括号出栈。
  5. 最后,将操作符栈中的剩余操作符全部出栈并添加到输出列表中。

标签:表示法,operator,token,操作符,求值,stack,表达式
From: https://www.cnblogs.com/allenxx/p/17734556.html

相关文章

  • c++正则表达式汇总
    一、校验字符的表达式1汉字:^[\u4e00-\u9fa5]{0,}$2英文和数字:^[A-Za-z0-9]+或[A−Za−z0−9]4,403长度为3-20的所有字符:^.{3,20}$4由26个英文字母组成的字符串:^[A-Za-z]+$5由26个大写英文字母组成的字符串:^[A-Z]+$6由26个小写英文字母组成的字符串:^[a-z]+$7由数字......
  • 3302. 表达式求值
    3302.表达式求值题目:3302.表达式求值-AcWing题库“表达式求值”问题,两个核心关键点:(1)双栈,一个操作数栈,一个运算符栈;(2)运算符优先级,栈顶运算符,和,即将入栈的运算符的优先级比较:如果栈顶的运算符优先级低,新运算符直接入栈以1+2+3x4x5举例,看是如何利用上述两个关键点实施计算......
  • MySQL正则表达式:模式匹配、中文匹配、替换、提取字符串
    在MySQL中,使用REGEXP或RLIKE操作符进行正则表达式匹配,而使用NOTREGEXP或NOTRLIKE操作符进行不匹配。一些常用的MySQL正则表达式语法:匹配字符:.:匹配任意字符(除了换行符)。[]:匹配方括号中的任意字符。[^]:匹配不在方括号中的任意字符。匹配重复:*:匹配零个或多个前面的字符。+:匹配一个......
  • lambda表达式递归报错
    lambda表达式递归报错报错代码:voidsolve(){intn=10;vector<int>adj[n+1];autodfs=[&](autoself,intu,intp)->void{for(autov:adj[u]){}};}在递归lambda表达式中引用的外部变量尽量不要出现形如......
  • jmeter正则表达式提取
    参考:https://www.cnblogs.com/uncleyong/p/10779268.html正则表达式提取器:后置处理器-正则表达式提取器Applyto:一般保持默认选择Mainsampleonly,这个用得最多,如果有sub-samples,可以选择第一个选项要检查的响应字段:用得最多的是主体,即header+body,可以从响应头,也可以从响应体......
  • Spring Boot 目录遍历--表达式注入--代码执行--(CVE-2021-21234)&&(CVE-2022-22963)&&
    SpringBoot目录遍历--表达式注入--代码执行--(CVE-2021-21234)&&(CVE-2022-22963)&&(CVE-2022-22947)&&(CVE-2022-2296)SpringBoot目录遍历(CVE-2021-21234)漏洞简介spring-boot-actuator-logview是一个简单的日志文件查看器作为SpringBoot执行器端点,在0.2.13版本之前存......
  • 算术表达式求值法(表达式求值)之前序表示法求值
    概念前序表示法,也称为前缀表示法或波兰表示法(Polishnotation),是一种用于表示数学表达式和算术运算的方法。这种表示法的特点是将运算符置于操作数之前,而不是像传统的中缀表示法(例如,2+3)将运算符置于操作数之间。前序表示法具有一些优点,尤其在计算机科学和计算器设计中非常有用。......
  • 正则表达式输入中文英文名
    请输入正确的姓名,支持中文或者英文(20位字符内),例如:杨颖/^([\u4e00-\u9fa5]{1,20}|[a-zA-Z\.\s]{1,20})$/如果想要支持名字中间输入·和.这样写,例如:迪丽热巴·迪力木拉提/^[\u4e00-\u9fa5a-zA-Z·.]+$/......
  • 正则表达式
    #按照邮件地址的格式(用户名@域名.后缀)来编写正则表达式#该正则表达式中包含了四个部分:#1.用户名:由一个或多个字母、数字、下划线、点、减号组成,且必须以字母或数字开头(用于描述用户名的部分用小括号括起来)#2.@符号:该部分只包含一个@符号#3.域名:由一个或多个字母、数字......
  • Java 8 Lambda 表达式解析
    Lambda表达式,也可称为闭包,它是推动Java8发布的最重要新特性。使用Lambda表达式可以使代码变的更加简洁紧凑。坦白的说,初次看见Lambda表达式瞬间头就大了,为了更好的理解,我们可以把Lambda表达式当作是一种匿名函数(对Java而言这并不完全正确,但现在姑且这么认为),简单地说,就是......