|
|
51CTO旗下网站
|
|
移动端

3.6.3 应用(3)

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

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

3.6.3 应用(3)

与前面相同, 这种转换只需要O(N)时间并经过一趟输入后工作完成。可以通过指定减法和加法有相同的优先级以及乘法和除法有相同的优先级而将减法和除法添加到指令集中去。需要注意的是,表达式a-b-c应转换成ab-c-而不是abc--。我们的算法进行了正确的操作, 因为这些操作符是从左到右结合的。一般情况未必如此, 比如下面的表达式就是从右到左结合的:223=28=256, 而不是43=64。我们将把取幂运算添加到操作符指令集中的问题留作练习。 

方法调用

检测平衡符号的算法提出一种在编译的过程语言和面向对象语言中实现方法调用的方式 由于Java是解释而不是编译执行的, 因此本节有些细节不可用到Java上, 但是一般的概念仍然可以在Java和许多其他语言上使用。。这里的问题是, 当调用一个新方法时, 主调例程的所有局部变量需要由系统存储起来, 否则被调用的新方法将会重写由主调例程的变量所使用的内存。不仅如此, 该主调例程的当前位置也必须要存储, 以便在新方法运行完后知道向哪里转移。这些变量一般由编译器指派给机器的寄存器, 但存在某些冲突(通常所有的方法都是获取指定给1号寄存器的某些变量), 特别是涉及递归的时候。该问题类似于平衡符号的原因在于, 方法调用和方法返回基本上类似于开括号和闭括号, 二者相同的想法应该都是行得通的。

当存在方法调用的时候, 需要存储的所有重要信息, 诸如寄存器的值(对应变量的名字)和返回地址(它可从程序计数器得到, 一般情况是在一个寄存器中)等, 都要以抽象的方式存在“一张纸上”并被置于一个堆(pile)的顶部。然后控制转移到新方法, 该方法自由地用它的一些值代替这些寄存器。如果它又进行其他的方法调用, 那么它也遵循相同的过程。当该方法要返回时, 它查看堆顶部的那张“纸”并复原所有的寄存器, 然后进行返回转移。90

显然, 所有全部工作均可由一个栈来完成, 而这正是在实现递归的每一种程序设计语言中实际发生的事实。所存储的信息或称为活动记录(activation record), 或叫作栈帧(stack frame)。在典型情况下, 需要做些微调整: 当前环境是由栈顶描述的。因此, 一条返回语句就可给出前面的环境(不用复制)。在实际计算机中的栈常常是从内存分区的高端向下增长, 而在许多非Java系统中是不检测溢出的。由于有太多的同时在运行着的方法, 因此栈空间用尽的情况总是可能发生的。显而易见, 栈空间用尽常是致命的错误。

在不进行栈溢出检测的语言和系统中, 程序将会崩溃而没有明显的说明; 而在Java中则抛出一个异常。

在正常情况下我们不应该越出栈空间, 发生这种情况通常是由失控递归(忽视基准情形)的指向引起。另一方面, 某些完全合法并且表面上无问题的程序也可以越出栈空间。图3-35中的例程打印一个集合, 该例程完全合法, 实际上是正确的。它正常地处理空集合的基准情形, 并且递归也没有问题。可以证明这个程序是正确的。但是不幸的是, 如果这个集合含有20000个元素要打印, 那么就要有表示第10行嵌套调用的20000个活动记录的栈。一般这些活动记录由于它们包含了全部信息而特别庞大, 因此这个程序很可能要越出栈空间。(如果20000个元素还不足以使程序崩溃, 那么可用更大的元素个数代替它。)

这个程序是称为尾递归(tail recursion)的使用极端不当的例子。尾递归涉及在最后一行的递归调用。尾递归可以通过将代码放到一个while循环中并用每个方法参数的一次赋值代替递归调用而被手工消除。它模拟了递归调用, 因为它什么也不需要存储; 在递归调用结束之后, 实际上没有必要知道存储的值。因此, 我们就可以带着在一次递归调用中已经用过的那些值转移到方法的顶部。图3-36中的方法显示手工改进后的程序。尾递归的去除是如此的简单, 以至于某些编译器能够自动完成。但是即使如此, 最好还是不要让你的程序带着尾递归。91


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

51CTO读书频道二维码


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

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

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

读 书 +更多

SOA概念、技术与设计

在本书中,Thomas ERL呈现了第一部端对端的教程,提供了从基层开始的面向服务的建模与设计的逐步指导。通过逐步的、清晰生动的、良好的SOA...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊