聊聊前序、中序、后序表达式
聊聊前序、中序、后序表达式在计算机科学和数学中表达式的表示方式直接影响计算过程的复杂度和实现方式。我们日常使用的数学表达式如3 5 * 2被称为中序表达式infix notation因为运算符位于操作数之间。然而这种表示方式对计算机并不友好因为需要处理运算符优先级和括号。为了解决这个问题诞生了前序表达式prefix notation和后序表达式postfix notation它们将运算符放在操作数之前或之后从而消除了括号和优先级歧义。本文将从原理出发深入剖析这三种表达式的特点、转换方法以及实际应用并辅以可运行的代码片段。### 什么是前序、中序、后序表达式这三种表达式都用于表示数学运算区别在于运算符和操作数的排列顺序-中序表达式运算符位于操作数之间例如A B。这是人类最直观的写法但需要括号和优先级规则来消除歧义如(A B) * C。-前序表达式运算符位于操作数之前例如 A B。也称为波兰表示法Polish Notation由波兰逻辑学家 Jan Łukasiewicz 提出。它无需括号因为运算顺序由位置决定。-后序表达式运算符位于操作数之后例如A B 。也称为逆波兰表示法Reverse Polish Notation, RPN是前序表达式的变体广泛应用于栈式计算器如 HP 计算器和编译器中。为什么前序和后序表达式对计算机更友好因为它们可以由一个简单的栈算法直接求值无需处理括号和优先级。例如表达式(3 5) * 2的中序形式需要明确括号但前序形式* 3 5 2和后序形式3 5 2 *则通过顺序计算即可。### 前序与后序表达式的求值原理求值前序和后序表达式的核心数据结构是栈。栈是一种后进先出LIFO的数据结构非常适合处理嵌套的运算顺序。#### 后序表达式求值后序表达式的求值算法如下1. 从左到右扫描表达式。2. 遇到操作数数字将其压入栈。3. 遇到运算符从栈中弹出两个操作数注意顺序先弹出的是右操作数后弹出的是左操作数执行运算结果压回栈。4. 扫描结束后栈顶即为最终结果。#### 前序表达式求值前序表达式的求值算法相反1. 从右到左扫描表达式。2. 遇到操作数压入栈。3. 遇到运算符从栈中弹出两个操作数先弹出的是左操作数后弹出的是右操作数执行运算结果压回栈。4. 扫描结束后栈顶即为结果。为什么方向相反因为前序表达式中运算符位于操作数之前从右向左扫描能先遇到操作数从而正确匹配。### 代码示例1后序表达式求值下面是一个用 Python 实现的后序表达式求值函数支持加减乘除运算pythondef evaluate_postfix(expression): 计算后序表达式的值。 参数 expression: 字符串操作数和运算符以空格分隔如 3 5 2 * 返回: 整数或浮点数结果 stack [] # 将表达式分割为 token 列表 tokens expression.split() for token in tokens: # 如果是操作数数字压入栈 if token.isdigit(): stack.append(int(token)) else: # 运算符弹出两个操作数 # 注意先弹出的是右操作数后弹出的是左操作数 right stack.pop() left stack.pop() # 根据运算符执行计算 if token : result left right elif token -: result left - right elif token *: result left * right elif token /: # 使用浮点除法避免整数截断 result left / right else: raise ValueError(f未知运算符: {token}) # 将结果压回栈 stack.append(result) # 最终栈顶即为结果 return stack.pop()# 测试计算 (3 5) * 2 的后序表达式postfix_expr 3 5 2 *print(f后序表达式: {postfix_expr})print(f计算结果: {evaluate_postfix(postfix_expr)}) # 输出 16输出后序表达式: 3 5 2 *计算结果: 16### 中序表达式转换为后序表达式在实际应用中我们通常将中序表达式转换为后序表达式或前序再求值。转换算法由 Edsger Dijkstra 提出称为调度场算法Shunting-yard algorithm。它使用一个操作符栈来调整运算符顺序同时输出后序表达式。算法核心规则- 从左到右扫描中序表达式。- 遇到操作数直接输出到结果列表。- 遇到运算符弹出栈中所有优先级不低于当前运算符的运算符输出它们然后将当前运算符压入栈。- 遇到左括号(直接压入栈。- 遇到右括号)弹出栈中运算符直到遇到左括号并输出这些运算符然后丢弃左括号。- 扫描结束后弹出栈中剩余运算符并输出。### 代码示例2中序转后序并求值下面是一个完整的程序将中序表达式转换为后序表达式然后求值pythondef infix_to_postfix(expression): 将中序表达式转换为后序表达式。 参数 expression: 字符串如 3 5 * 2 返回: 后序表达式字符串如 3 5 2 * # 定义运算符优先级 precedence {: 1, -: 1, *: 2, /: 2} output [] # 存放后序表达式 token stack [] # 操作符栈 # 分割表达式假设操作数和运算符以空格分隔 tokens expression.split() for token in tokens: # 如果是操作数数字直接输出 if token.isdigit(): output.append(token) elif token (: stack.append(token) elif token ): # 弹出直到左括号 while stack and stack[-1] ! (: output.append(stack.pop()) stack.pop() # 移除左括号 else: # 运算符弹出优先级不低于当前运算符的运算符 while stack and stack[-1] ! ( and precedence.get(stack[-1], 0) precedence.get(token, 0): output.append(stack.pop()) stack.append(token) # 弹出剩余运算符 while stack: output.append(stack.pop()) return .join(output)# 测试转换infix_expr 3 5 * 2 # 对应 (3 (5 * 2))postfix_expr infix_to_postfix(infix_expr)print(f中序表达式: {infix_expr})print(f后序表达式: {postfix_expr})# 使用之前定义的求值函数print(f计算结果: {evaluate_postfix(postfix_expr)}) # 输出 13输出中序表达式: 3 5 * 2后序表达式: 3 5 2 * 计算结果: 13### 深入原理为什么前序和后序无需括号中序表达式的歧义来源于运算符优先级和结合性。例如3 5 * 2如果不加括号按照数学规则是3 (5 * 2) 13但若误解为(3 5) * 2 16则错误。前序和后序表达式通过位置固定了运算顺序。考虑前序表达式 3 * 5 2。从右向左扫描遇到2和5压栈遇到*弹出5和2得10压栈然后遇到3压栈遇到弹出3和10得13。这个顺序天然对应了3 (5 * 2)无需括号。后序表达式3 5 2 * 同理。从左向右扫描3压栈5压栈2压栈遇到*弹出5和2得10压栈遇到弹出3和10得13。因此前序和后序表达式本质上将运算顺序编码到了扫描方向或位置中消除了对括号的依赖。### 总结前序、中序和后序表达式是表达式计算的三种核心表示法。中序表达式虽符合人类直觉但需要复杂的解析前序和后序表达式通过栈算法实现高效求值广泛应用于编译器、计算器和科学计算中。本文通过原理剖析和可运行代码展示了后序表达式求值、中序转后序的调度场算法并解释了为何前序和后序无需括号。理解这些概念有助于深入掌握计算机语言解析和算法设计。无论你是学习数据结构还是开发编程语言这三者都是不可或缺的基础。

相关新闻

间,最大化 CPU 利用率。 异步编程通过事件循环实现任务调度:当一个任务因 IO 操作需要等待时,事件循环会暂停该任务,切换到其他 ...

间,最大化 CPU 利用率。 异步编程通过事件循环实现任务调度:当一个任务因 IO 操作需要等待时,事件循环会暂停该任务,切换到其他 ...

异步编程:最大化 CPU 利用率的秘密武器 引言:为什么我们需要异步编程?想象一下,你正在一家繁忙的咖啡店排队点单。店员在等咖啡机煮咖啡时,如果只是呆呆站着等,那么后面的顾客就要等更久。但如果店员在等待…

2026/7/25 19:25:15 阅读更多 →
CVE-2022-25845 FastJSON(com.alibaba:fastjson)

CVE-2022-25845 FastJSON(com.alibaba:fastjson)

springboot 升级以及漏洞处理 CVE-2022-25845 FastJSON(com.alibaba:fastjson)包引发的漏洞fastJson-1.2.68.jar com.alibaba.fastjson.parser.ParserConfig com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer FastJSON 默认关闭 auto…

2026/7/25 19:25:15 阅读更多 →
UGC数字人系统开发实战:从AI技术整合到工程架构设计

UGC数字人系统开发实战:从AI技术整合到工程架构设计

在数字人技术从实验室走向大众消费市场的过程中,降低使用门槛一直是核心挑战。JoyAI App 最新推出的 UGC 数字人功能,通过简化生成流程和强化个性化定制,让普通用户也能快速创建专属虚拟玩伴,这标志着数字人技术正从专业工具向日常应用转变。 实际开发一个具备类似能力的数…

2026/7/25 19:24:15 阅读更多 →

最新新闻

涂胶显影机(Track)技术岗普通专家工程师完整JD(12维度)+对外简化版JD

涂胶显影机(Track)技术岗普通专家工程师完整JD(12维度)+对外简化版JD

一、内部完整版JD(12维度专业拆解普通专家职级)模块级技术负责人职级定位说明:介于高级工程师与首席专家/技术总监之间,为公司,脱离单点执行与带队攻坚,主打技术立项、方案定标、技术壁垒搭建、产品线技术兜…

2026/7/25 19:35:22 阅读更多 →
观察使用 Taotoken 后月度 API 成本与 token 消耗的明细变化

观察使用 Taotoken 后月度 API 成本与 token 消耗的明细变化

观察使用 Taotoken 后月度 API 成本与 token 消耗的明细变化 对于独立开发者或中小型团队而言,大模型 API 的调用成本是项目运营中一项重要的考量。在直接对接多个模型供应商时,账单分散、用量模糊是常见痛点,使得成本控制和预算规划变得困难…

2026/7/25 19:35:22 阅读更多 →
Codex AI编程助手引擎替换指南:从OpenAI平滑迁移至DeepSeek/Qwen

Codex AI编程助手引擎替换指南:从OpenAI平滑迁移至DeepSeek/Qwen

如果你是一名开发者,最近可能已经注意到一个趋势:越来越多的团队开始将AI编程助手从单一的闭源模型转向更灵活、更可控的国产大模型。但这个过程远不止“换个API地址”那么简单。从权限配置、模型适配,到工作流调整,每一步都可能藏着意想不到的“坑”。 本文要解决的,正是…

2026/7/25 19:35:22 阅读更多 →
【2024员工关怀效能白皮书】:基于237家企业的A/B测试数据——部署AI HR后心理安全感提升41%,但93%团队漏掉关键触发节点

【2024员工关怀效能白皮书】:基于237家企业的A/B测试数据——部署AI HR后心理安全感提升41%,但93%团队漏掉关键触发节点

更多请点击: https://codechina.net 第一章:AI HR员工关怀的范式迁移与效能悖论 传统HR员工关怀长期依赖经验驱动、周期性调研与人工干预,而AI技术正推动其从“响应式服务”跃迁至“预测式共生”。这一范式迁移并非线性升级,而是…

2026/7/25 19:35:22 阅读更多 →
【GMAT AI备考黑箱解密】:斯坦福教育AI实验室未公开的6层知识图谱映射技术,让AI真正“懂”GMAT逻辑

【GMAT AI备考黑箱解密】:斯坦福教育AI实验室未公开的6层知识图谱映射技术,让AI真正“懂”GMAT逻辑

更多请点击: https://kaifayun.com 第一章:GMAT AI备考黑箱解密:从符号推理到认知建模的范式跃迁 传统GMAT备考工具长期依赖规则引擎与静态题库匹配,其底层逻辑建立在显式符号推理之上——例如将“代数不等式求解”映射为预设的i…

2026/7/25 19:35:22 阅读更多 →
涂胶显影机(Track)技术岗中级工程师完整 JD(12 维度内部专业版)

涂胶显影机(Track)技术岗中级工程师完整 JD(12 维度内部专业版)

1. 对标职级 行业统一骨干职级,设备原厂对标 P3/P4、晶圆厂 E3/E4;职称序列中级工程师,介于初级工程师与高级工程师之间,属于独立模块负责人,是部门核心执行骨干。 任职年限门槛:初级工程师满 2 年 总行业…

2026/7/25 19:34:18 阅读更多 →

日新闻

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您的…

2026/7/25 0:00:35 阅读更多 →
C++ string类模拟实现:从深拷贝到内存管理的完整指南

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述:为什么我们要“手撕”string类?在C的学习道路上,尤其是从C语言过渡到C的“初阶”阶段,string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了,、find、substr,几个操作符和函数…

2026/7/25 0:00:35 阅读更多 →
三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看,“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具,而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源,比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:35 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/25 5:08:22 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/25 5:13:53 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻