当前课程知识点:数据结构(上) > 第四章 栈与队列 > (c4)栈应用:中缀表达式求值 > 04C4-5 算法细节
不同情况的处理方法
可以由这样一段代码描述并实现
首先如果栈顶运算符的优先级
低于当前的运算符
比如运算符的栈顶位置是一个加号
而我们的表达式
当前扫描到的位置却是乘号
那么就属于这样的一种情况
在这样的情况下
栈顶的运算符
还没有等到应该执行的时机
因此就需要将当前的运算符乘号
推入运算符栈中
同时将目光
转向表达式中的下一个字符
再来考虑相反的情况
也就是栈顶运算符的优先级
相对于当前运算符更高
比如颠倒过来 栈顶是一个乘号
而当前运算符是一个加号
这就意味着此时
栈顶运算符的执行时机已到
因此这个分支的实质动作
也就是执行相应的运算
我们来看一下
首先要从操作符栈中
弹出当前的栈顶操作符
如果它是阶乘
也就是我们这里所纳入的
唯一的一个一元运算符
我们就从操作数栈中
弹出栈顶一个元素
并且与这样一个阶乘运算符
去执行相应的运算
而计算的结果呢
我们还需重新将它
推回到操作数栈中去
当然 除此之外的
在我们这里都是二目运算符
因此我们需要从操作数栈中
弹出一个 两个操作数
并且将这两个操作数交给
当前的这个运算符 执行对应的运算
还要将运算所得的结果
重新纳回操作数栈中去
仍以刚才这个情形为例
假设当前的栈顶运算符是乘号
高于当前的加号这个运算符
那么就应该从运算数栈中
取出顶端的两个元素
比如2和3 执行相应的乘法运算
并且将运算的结果重新纳回栈中
崇尚简洁的同学 或许会注意到
我们这里对应于第一个运算数
以及第二个运算数
所引入的两个局部变量
从某种意义上讲 似乎是多余的
因为我们可以把整个这样的
一个计算过程
写成这样更为紧凑的一个形式
弹出一个运算数 再弹出一个运算数
然后
对应于相应的运算符 执行相应的计算
并随即将计算的结果推回运算数栈中
那么问题是我们这里为什么没有
采用这样一种更为简洁紧凑的形式呢?
我们将这个作为大家在课后的
思考以及讨论的题目
最后 我们再来考察优先级相等的情况
为此或许我们应该首先来温习一下
刚才所定义的那张优先级表
纵观这张表
我们会发现 只有两处会出现等号
第一处当前的栈顶是左括号
而当前的字符却是右括号
不难看出 只要原表达式是语法正确的
这个右(注意:应该是左)括号肯定是在
此前某个位置出现
而且恰好与这个右括号彼此匹配
在原来的表达式中
它们的任务或者使命
只不过是为了强制地界定
介乎它们之间的
那样一个子表达式的优先级
在这个子表达式中
可能会有各种运算符
但在经过一系列的运算之后
可能它们都相继执行过
并且逐个消失
等效于它们从来就没有存在过
而当这样一对括号
重新彼此相逢的时候
子表达式已经完全计算和处理完毕
此时它所对应的无非是一个数字
也就是说 这对括号的
历史使命已经完成
现在到了它们联手退出舞台的时候了
基于以上的分析
我们就不难理解
对于这种情况的处理方法了
具体来说 只需简洁地
将运算符栈中的当前运算符
比如说左括号 弹出
同时在表达式中
我们也忽略掉
与之对应的那个右括号
而将注意力转向下一个字符
那么另一种情况
也就是表达式末尾结束标志\0字符
也应该如此来处理吗?
没错 的确应该这样处理
不要忘了 在我们开始计算之前
我们首先已经将\0推入栈中
作为一个铺垫
如果将这个铺垫的\0
视作是一个左括号
那么作为整个表达式
结束标志的那个\0
自然也就对应一个右括号
如此看来 有朝一日一旦它们相逢
也就完全等效于
一对匹配的括号相逢
所以我们采用刚才的那种方式
将前者直接弹出
从而使得栈清空
并且同时将注意力
跳过最后的这个字符
也是再恰当不过的
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)计算
--演示
--(a)计算--作业
-(b)计算模型
-(b)计算模型--作业
-(c)大O记号
-(c)大O记号--作业
-(d)算法分析
-(d)算法分析--作业
-(e)迭代与递归
-(e)迭代与递归--作业
-(xc)动态规划
-- 演示
-(xc)动态规划--作业
-本章测验--作业
-(a)接口与实现
--02A-5 复制
-(a)接口与实现--作业
-(b)可扩充向量
-(b)可扩充向量--作业
-(c)无序向量
--02C-1 概述
--02C-3 插入
--02C-6 查找
--02C-8 遍历
-(c)无序向量--作业
-(d1)有序向量:唯一化
-(d1)有序向量:唯一化--作业
-(d2)有序向量:二分查找
-(d2)有序向量:二分查找--作业
-(d3)有序向量:Fibonacci查找
-(d3)有序向量:Fibonacci查找--作业
-(d4)有序向量:二分查找(改进)
-(d4)有序向量:二分查找(改进)--作业
-(d5)有序向量:插值查找
-第二章 向量(下)--(d5)有序向量:插值查找
-(e)起泡排序
--02E-2 改进
--02E-3 反例
-(e)起泡排序--作业
-(f)归并排序
-(f)归并排序--作业
-本章测验--作业
-(a)接口与实现
--03A-4 实现
-(a)接口与实现--作业
-(b)无序列表
--03B-2 查找
-(b)无序列表--作业
-(c)有序列表
--03C-3 查找
-(c)有序列表--作业
-(d)选择排序
--03D-1 构思
--03D-2 实例
--03D-3 实现
--03D-4 推敲
--03D-6 性能
-(d)选择排序--作业
-(e)插入排序
--03E-1 经验
--03E-2 构思
--03E-3 对比
--03E-4 实例
--03E-5 实现
-(e)插入排序--作业
-(xd)习题辅导:LightHouse
-本章测验--作业
- (a)栈接口与实现
--04A-1 栈
--04A-2 实例
--04A-3 实现
- (a)栈接口与实现--作业
-(c1)栈应用:进制转换
-第四章 栈与队列--(c1)栈应用:进制转换
-(c2)栈应用:括号匹配
-(c2)栈应用:括号匹配--作业
-(c3)栈应用:栈混洗
-第四章 栈与队列--(c3)栈应用:栈混洗
-(c4)栈应用:中缀表达式求值
-(c4)栈应用:中缀表达式求值--作业
-(c5)栈应用:逆波兰表达式
-第四章 栈与队列--(c5)栈应用:逆波兰表达式
-(d)队列接口与实现
--04D-1 接口
--04D-2 实例
--04D-3 实现
-第四章 栈与队列--本章测验
-(a)树
--05A-1 动机
--05A-2 应用
-(a)树--作业
-(b)树的表示
--05B-2 父亲
--05B-3 孩子
-第五章 二叉树--(b)树的表示
-(c)二叉树
-(c)二叉树--作业
-(d)二叉树实现
-(d)二叉树实现--作业
-(e1)先序遍历
-(e1)先序遍历--作业
-(e2)中序遍历
-第五章 二叉树--(e2)中序遍历
-(e4)层次遍历
-第五章 二叉树--(e4)层次遍历
-(e5)重构
-(e5)重构--作业
-本章测验--作业
-(a)概述
-(a)概述--作业
-(b1)邻接矩阵
-(b1)邻接矩阵--作业
-(c)广度优先搜索
--06C-2 策略
--06C-3 实现
--06C-5 实例
-(c)广度优先搜索--作业
-(d)深度优先搜索
--06D-1 算法
--06D-2 框架
--06D-3 细节
-(d)深度优先搜索--作业
-第六章 图--本章测验