递归是一个很有用的设计技术。在某些情况下,对于用其他方法很难解决的问题,使用递归就能给出一个自然、直接的简单解法。
1、递归定义
递归定义由两部分组成。第一部分称作定位点或是基本例子,列出了构造集合中其他元素构造块的基本元素。第二部分,给出构造除基本元素之外的或是已经创建好的新对象的条件。这个条件可以再三地被用来生成新对象。
递归定义有两个目的:如前撰述的产生新元素,以及检查它是否是集合的一个元素。在检查时,先将一个问题简化。如果简化后仍然太复杂就继续简化,起到简化后的问题指向定位点。
2、方法调用和递归实现
方法调用时应当保存什么信息呢?道德是自动(局部)变量。如果一个包含局部变量x声明的方法f1()调用f2()方法,而f2()局部地声明了变量x,那么系统必须区分这两个变量x。如果f2()使用变量x,这表示它自己定义的x;如果f2()赋值给x,那么f1()的变量x的值不应被改变。当f2()结束后,f1()可以使用在f2()调用前赋值给x。当f1()和f2()相同时,就是一个方法对它自身的递归调用。那么系统是如何区分这两个变量x的呢?
第一种方法(包括main()方法)的状态都以所有自动变量的内容、方法的参数值以及表示调用程序重新开始处的返回地址为特征。包含所有这些信息的数据域定位在运行堆栈中,称为活动记录或是栈结构。只要其中的一个方法在执行,属于它的活动记录就存在。这个记录是该方法信息的一个私有池,一个存储正确执行及返回调用位置的必要信息的仓库。活动记录的生存周期通常很短,因为它们是在进入方法时动态分配并且在方法退出时动态回收的。只有main()的活动记录比其他活动记录的生存周期长些。
一个活动记录通常包含以下信息:
该方法所有的参数值,首单元地址(如果传递的是数组或是引用变量的话),所有其他数据项的拷贝。
可以存在别处的局部变量,活动记录只包含它们的描述符和指向它们存储地址的指针。
存储一个返回地址将控制权给调用程序,这个地址是紧跟在调用指令后的第一条指令的地址。
一个动态连接,即一个指向调用程序活动记录的指针。
一个未被声明为void类型的方法的返回值。因为每个调用的活动记录的大小都是不同的,所以返回值就放在调用程序的活动记录的前面。
如前撰述,如果一个方法被main()或另一个方法调用,那么它的活动记录就创建在运行堆栈中。运行堆栈总是反映方法的当前状态。例如,假设main()调用方法f1(),f1()调用f2(),而f2()又调用f3()。如果f3()正在执行中,那么运行堆栈的状态如图所示。根据堆栈的性质,如果弹出了f3()的活动记录,只要将指针移到f3()的返回值下面就可以,那么f2()又恢复运行,并可以自由地访问重新被激活运行所必需的信息私有池。另一方面,如果f3()刚巧又调用了另一个该方法f4(),那么运行堆栈将上移栈顶指针,因为f4()的活动记录被创建在堆栈中并且f3()会被挂起。
无论何时调用一个方法都会创建一个活动记录,这使得系统可以正确处理递归。递归是调用一个和调用者同名的方法,所以一个递归调用并不是一个方法调用其自身,而是方法的一个实例调用相同方法的另一个实例。在计算机内部,这些调用是用不同的活动记录表示并由系统区分的。
小结:
递归通常比它的迭代形式效率低。但是打个比方,如果一个递归程序执行100ms,而它的迭代公需要10ms,那么尽管后者比前者快10倍,这种差别还是很难分辨的。如果要比清晰性、易读性和代码的简洁性,那么这两个版本执行时间上的差别就可以忽略。递归解决方案通常比迭代简单,而且和源算法的逻辑一致性强。阶乘和幂运算就是这样的例子。
分享到:
相关推荐
关于递归的误区:深入解析递归的时间复杂度与优化策略 在计算机科学领域,递归是一种常见的算法设计技巧,其基本思想是将问题分解为更小的子问题,直至达到可以直接解决的基本情况,然后逐步返回求解原问题。递归因...
关于递归算法时间复杂度分析的探讨,是一个深入理解算法效率和优化的关键议题。递归,作为解决问题的一种强大工具,其本质是将复杂问题分解为更简单的子问题,通过求解这些子问题来达到最终解决方案的目的。然而,...
关于递归教学的探讨 递归是计算机科学中一种核心的程序设计技术,它涉及到函数或过程在其执行过程中调用自身的过程。递归在程序设计基础、数据结构和算法设计等课程中扮演着重要角色,但也是教学上的难点。递归教学...
递归优化(使用缓存) 递归是 Python 中的一种重要编程技术,但是其缺陷之一是计算速度慢。优化递归是提高计算效率的重要步骤,本文将讨论使用缓存来优化递归的方案。 递归的优化思路 ---------------- 递归的...
在计算机科学中,递归是一种强大的编程概念,它涉及到函数或过程在其定义中调用自身。递归在解决复杂问题时特别有用,因为它允许将大问题分解为更小的相似子问题,直到达到基本情况,然后逐步合并解决方案。本文将...
x=fib(n-1)+fib(n-2);
关于递归操作,相信大家都已经不陌生。简单地说,一个函数直接或间接地调用自身,是为直接或间接递归。例如,我们可以使用递归来计算一个单向链表的长度: 代码如下: public class Node { public Node(int value,...
c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘 n!c++ 递归 阶乘...
汉诺塔问题是一个经典的计算机科学问题,源自印度的古老传说,它涉及到三个柱子和一堆大小...以上就是关于“C++递归实现汉诺塔问题”的详细解析,它涵盖了递归算法设计的基本概念、实例代码以及相关的计算机科学知识。
递归互斥信号量.zip"这个压缩包中,包含的源代码很可能是FreeRTOS中关于递归互斥信号量的示例应用。通过分析这些源码,我们可以学习如何创建、获取和释放递归互斥信号量,以及如何在实际项目中正确使用它们。 创建...
《递归九讲2021 7-9》是一个关于递归算法的专题学习资料,涵盖了递归在解决各种问题中的应用,包括二叉树类问题和排列类问题。通过对递归的理解和掌握,我们可以解决更复杂的问题,提高编程效率。本资料包括三章互动...
文件列表中有一个名为 "2010级软件工程2班2010416495刘士强(实验三)实验报告.doc" 的文档,这很可能是刘士强同学完成的关于递归下降分析的实验报告,里面可能包含了他对递归下降分析方法的理论理解和实际操作步骤...
根据给定文件的信息,我们可以总结出以下关于递归与分治技术的重要知识点: ### 一、递归的基本概念 #### 定义: 递归是一种在程序设计中非常重要的方法,它指的是在一个函数或过程中直接或间接地调用自身来解决...
以下是关于递归表达式计算器的一些关键知识点: 1. **递归的基本概念**:递归是一种解决问题的方法,它将问题分解为更小的子问题,直到子问题可以直接解答。在计算表达式时,递归通常用于处理如括号嵌套、函数调用...
标题提到的"递归Recursion)1"可能是指一个关于递归的系列教程或讨论的第一个部分,重点是介绍递归的基本概念和QL中的应用。 描述中提到了一个使用递归谓词`getANumber()`的例子,这个谓词用于生成0到100之间的所有...
"www.pudn.com.txt"可能是一个文档,提供了关于递归算法的详细资料,可能包括递归的基本概念、递归函数的定义、递归的特性以及如何设计递归算法等。在递归算法中,通常有一个或多个基本情况(base cases),这些是不...
文件`www.pudn.com.txt`可能是一个文档,提供了关于递归概念的进一步解释,或者是项目的说明或者代码注释。 在VC++中实现递归,你需要确保以下几点: 1. **正确设定基础情况**:递归函数必须有一个明确的基础情况...
递归算法是计算机科学中的一个重要概念,它是一种解决问题的方法,其中函数或过程调用...以上是关于递归算法的一些基本知识和应用场景。通过深入学习和实践,你可以更好地掌握递归算法,并将其运用到各种实际问题中。
**标题解析:**"recursion-see-recursion:关于递归和垃圾的演讲幻灯片",这个标题表明了主题是关于编程中的递归概念,同时可能涉及到了内存管理,特别是“垃圾”的提及,可能指的是JavaScript环境中的垃圾回收机制。...
从提供的压缩包文件名来看,它们可能包含了关于递归和分治策略的详细讲解,如"递归与分治.ppt",以及可能的实例分析。通过学习这些材料,你可以更深入地理解递归在C/C++中的应用和实践。 总之,掌握递归是提升编程...