|
|
|
|
移动端

3.6.3 应用(2)

《数据结构与算法分析:Java语言描述(原书第3版)》第3章表、栈和队列,本章讨论最简单和最基本的三种数据结构。实际上, 每一个有意义的程序都将显式地至少使用一种这样的数据结构, 而栈则在程序中总是要被间接地用到, 不管我们在程序中是否做了声明。本节为大家介绍应用。

作者:冯舜玺/陈越 译来源:机械工业出版社|2016-04-13 17:52

3.6.3 应用(2)

计算一个后缀表达式花费的时间是O(N), 因为对输入中的每个元素的处理都是由一些栈操作组成从而花费常数的时间。该算法的计算是非常简单的。注意, 当一个表达式以后缀记号给出时, 没有必要知道任何优先的规则, 这是一个明显的优点。

中缀到后缀的转换

栈不仅可以用来计算后缀表达式的值, 而且还可以用栈将一个标准形式的表达式(或叫作中缀表达式(infix))转换成后缀式。我们通过只允许操作+,*,(,), 并坚持普通的优先级法则而将一般的问题浓缩成小规模的问题。此外, 还要进一步假设表达式是合法的。假设将中缀表达式

a+b*c+(d*e+f)*g

转换成后缀表达式。正确的答案是abc*+de*f+g*+。

当读到一个操作数的时候, 立即把它放到输出中。操作符不立即输出, 从而必须先存在某个地方。正确的做法是将已经见到过但尚未放到输出中的操作符推入栈中。当遇到左圆括号时我们也要将其推入栈中。计算从一个空栈开始。87

如果见到一个右括号, 那么就将栈元素弹出, 将弹出的符号写出直至遇到一个(对应的)左括号, 但是这个左括号只被弹出并不输出。

如果我们见到任何其他的符号(+,*,(), 那么我们从栈中弹出栈元素直到发现优先级更低的元素为止。有一个例外: 除非是在处理一个)的时候, 否则我们决不从栈中移走(。对于这种操作,+的优先级最低, 而(的优先级最高。当从栈弹出元素的工作完成后, 我们再将操作符压入栈中。

最后, 如果读到输入的末尾, 我们将栈元素弹出直到该栈变成空栈, 将符号写到输出中。

这个算法的想法是, 当看到一个操作符的时候, 把它放到栈中。栈代表挂起的操作符。然而, 栈中有些具有高优先级的操作符现在知道当它们不再被挂起时要完成使用, 应该被弹出。这样, 在把当前操作符放入栈中之前, 那些在栈中并在当前操作符之前要完成使用的操作符被弹出。详细的解释见下表:

圆括号增加了额外的复杂因素。当左括号是一个输入符号时我们可以把它看成是一个高优先级的操作符(使得挂起的操作符仍是挂起的), 而当它在栈中时把它看成是低优先级的操作符(从而不会被操作符意外地删除)。右括号被处理成特殊的情况。

为了理解这种算法的运行机制, 我们将把上面长的中缀表达式转换成后缀形式。首先, 符号a被读入, 于是它被传向输出。然后, ‘+’被读入并被放入栈中。接下来b读入并流向输出。这一时刻的状态如下:

接着*号被读入。操作符栈的栈顶元素比*的优先级低, 故没有输出且*进栈。接着, c被读入并输出。至此, 我们有

后面的符号是一个+号。检查一下栈我们发现, 需要将*从栈弹出并把它放到输出中; 弹出栈中剩下的+号, 该算符不比刚刚遇到的+号优先级低而是有相同的优先级; 然后, 将刚刚遇到的+号压入栈中

下一个被读到的符号是一个(, 由于有最高的优先级, 因此它被放进栈中。然后, d读入并输出

继续进行, 我们又读到一个*。由于除非正在处理闭括号否则开括号不会从栈中弹出, 因此没有输出。下一个是e, 它被读入并输出

再往后读到的符号是+。我们将*弹出并输出, 然后将+压入栈中。这以后, 我们读到f 并输出

现在, 我们读到一个), 因此将栈元素直到(弹出, 我们将一个+号输出

下面又读到一个*; 该算符被压入栈中。然后, g被读入并输出

现在输入为空, 因此我们将栈中的符号全部弹出并输出, 直到栈变成空栈


喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:342347198

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

计算机与网络基础知识——考点解析及模拟训练

本书是根据全国计算机技术与软件专业技术资格(水平)考试的“计算机网络管理员考试大纲”所要求的考试范围而编写的辅导用书。全书共分10章...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊