当前位置: 首页 > news >正文

栈的应用:表达式求值

一、核心问题:表达式求值的难点

对于像 3*(7-2)# 这样的表达式,直接计算会面临 “运算顺序” 的问题:

  • 先算括号里的 7-2,还是先算乘法?
  • 如何处理运算符的优先级(乘除高于加减)?
  • 如何匹配括号(括号内的要优先计算)?

栈的作用就是 “管理运算顺序”

  • 用两个栈:
    • OPND 栈:存操作数(如 372 )和中间结果(如 515 )。
    • OPTR 栈:存运算符(如 *(- )和边界符(如 # )。
  • 通过 “比较运算符优先级”,决定是 “压栈等待” 还是 “弹出计算”。

二、关键规则:算符优先关系表

 

这张表是 “指挥中心”,决定运算符的优先级:

  • 表格里的 θ₁ 是 栈顶运算符θ₂ 是 当前扫描到的运算符
  • 比较结果:
    • <:当前运算符优先级更高 → 压入 OPTR 栈,等待后续计算。
    • >:栈顶运算符优先级更高 → 弹出栈顶运算符,从 OPND 取数计算。
    • =:括号匹配(如 ( 和 ) 相遇),弹出栈顶的 (,继续扫描。

举个简单例子:

  • 栈顶是 +θ₁),当前运算符是 *θ₂):查表格,+ 和 * 的交叉是 < → * 优先级更高,* 压栈。
  • 栈顶是 *θ₁),当前运算符是 +θ₂):查表格,* 和 + 的交叉是 > → * 优先级更高,先弹出 * 计算。

三、算法步骤(结合图片里的流程)

以 3*(7-2)# 为例,完整走一遍流程:

1. 初始化
  • OPTR 栈压入 #(作为表达式的 “起始边界符”)。
  • OPND 栈为空。
  • 扫描指针指向表达式第一个字符 '3'
2. 循环处理(直到扫描到 # 且栈顶也是 #

核心逻辑

  • 遇到 操作数(如 372 )→ 压入 OPND 栈。
  • 遇到 运算符(如 *(- )→ 查 “优先关系表”,决定是 “压栈” 还是 “计算”。

逐步演示

步骤扫描字符 ch操作说明
1'3'压入 OPND 栈OPND: [3]OPTR: [#]
2'*'比较 OPTR 栈顶 # 和 * → <* 压入 OPTR 栈 → OPTR: [#, *]
3'('比较 OPTR 栈顶 * 和 ( → <( 压入 OPTR 栈 → OPTR: [#, *, (]
4'7'压入 OPND 栈OPND: [3, 7]
5'-'比较 OPTR 栈顶 ( 和 - → <- 压入 OPTR 栈 → OPTR: [#, *, (, -]
6'2'压入 OPND 栈OPND: [3, 7, 2]
7')'比较 OPTR 栈顶 - 和 ) → >弹出 -,计算 7-2=5,结果压入 OPND → OPND: [3, 5];然后比较栈顶 ( 和 ) → =,弹出 (
8'#'比较 OPTR 栈顶 * 和 # → >弹出 *,计算 3*5=15,结果压入 OPND → OPND: [15]
9'#'扫描结束,返回 OPND 栈顶结果 15
3. 终止条件

当扫描到 #,且 OPTR 栈顶也是 # 时,循环结束,OPND 栈顶就是最终结果。

四、代码逻辑解析(结合图片里的函数)

以下是核心函数的逻辑拆解(对应图片里的 EvaluateExpression 函数):

1. 初始化栈
InitStack(OPTR); Push(OPTR, '#'); // OPTR 栈初始化,压入 #
InitStack(OPND); ch = getchar();  // OPND 栈初始化,读第一个字符
2. 循环处理表达式
while (ch != '#' || GetTop(OPTR) != '#') { // 没扫描完或栈顶不是 #if (!In(ch)) { // ch 不是运算符 → 压入 OPNDPush(OPND, ch); ch = getchar(); } else { // ch 是运算符 → 比较优先级switch (Precede(GetTop(OPTR), ch)) { case '<': // 当前运算符优先级高 → 压栈Push(OPTR, ch); ch = getchar(); break;case '>': // 栈顶运算符优先级高 → 弹出计算Pop(OPTR, theta); // 弹出运算符Pop(OPND, b); Pop(OPND, a); // 弹出两个操作数Push(OPND, Operate(a, theta, b)); // 计算后压入结果break;case '=': // 括号匹配 → 弹出 (,继续扫描Pop(OPTR, x); ch = getchar(); break;}}
}
3. 返回结果
return GetTop(OPND); // OPND 栈顶就是结果

五、关键函数说明

  1. In(ch):判断 ch 是否是运算符(+-*/()# )。
  2. Precede(θ₁, θ₂):查 “优先关系表”,返回 <> 或 =
  3. Operate(a, theta, b):执行运算(如 a + ba * b ),注意顺序(a 是栈底的数,b 是栈顶的数,比如 7-2 中 a=7b=2 )。

六、总结

栈在表达式求值中的核心作用是 “管理运算顺序”

  • 用 OPTR 栈 “暂缓” 低优先级的运算符,保证高优先级的先计算。
  • 用 OPND 栈存操作数和中间结果,随时弹出参与计算。
  • 整个过程靠 “算符优先关系表” 指挥,实现自动遵循 “先乘除后加减、先括号内后括号外” 的规则。

相关文章:

  • Linux随笔
  • 滚珠导轨在光学设备中如何实现微米级运动?
  • 《Coevolutionary computation and its application》协同演化及其应用中文对照·第一章
  • Visual Studio如何引入第三方头文件——以部署OpenGL为例
  • Stream流性能分析及优雅使用
  • NER实践总结,记录一下自己实践遇到的各种问题。
  • [JS逆向] 烯牛数据
  • HCIE-Datacom笔试题库
  • LVS、NGINX、HAPROXY的调度算法
  • if(!p)等价于 if(p==0)
  • C#Winform中DevExpress下的datagridview 特定列可编辑,其他列不可编辑
  • 6个月Python学习计划 Day 14 - 阶段复盘 + 项目练习测试
  • 功率估计和功率降低方法指南(1~2)
  • C++ PCL库 预编译安装与排错:common is required but boost was not found
  • ROS2性能狂飙:C++11移动语义‘偷梁换柱’实战
  • 爬虫学习记录day1
  • 【Linux庖丁解牛】—自定义shell的编写!
  • Elasticsearch的搜索流程描述
  • 《Docker》架构
  • 舆情监控系统爬虫技术解析
  • 如何做vip微信电影网站/营销推广工作内容
  • 公司网站制作专业公司/链接交换平台
  • h5制作微信小程序/页面优化的方法有哪些
  • 网站推广的方式有哪些/seo快速排名软件价格
  • 大网站制作公司/长沙seo关键词
  • 安陆做网站公司/中山疫情最新消息