`
Candy_Code
  • 浏览: 13923 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

关于递归,不得不说的

阅读更多
二话不说,先上代码
public class TestRecursion{
	//递归方法
	public static  void fun(int i){
		if(i > 0){
			i--;
			fun(i);
			System.out.print(i);
		}
		System.out.print(" ok ");
	}
	public static void main(String args[]){
		fun(10);
	}
}


这段代码看似简单,其中的奥秘你却未必尽知。
首先.什么是递归?相信大家都知道,就是方法直接或间接地调用自身。
要想深入理解递归,得从栈的角度去看待方法间的调用。
先来看一个简单的例子:

public void a(){}
public void b(){
	System.out.println("Hello");
	a();
	System.out.println("boy");
}


方法b()调用了方法a(),此时程序不再顺序执行,而是发生跳转。CPU首先将下一条机器指令的地址以及相关的参数信息压入栈中,然后程序跳转到a()的方法体中。当a()方法返回时,CPU会执行出栈操作,取出上一次存储的机器指令的地址以及参数信息,即System.out.println("boy")(当然了,System.out.println()不是一条机器指令,而是被翻译成多条机器指令)
递归方法也是一个道理,只不过,调用者与被调用者是同一个方法。
递归与循环的有些相似,但又截然不同。循环没有方法间的调用关系,也就没有指令地址的压栈、出栈,它仅仅指令地址的改变。
现贴出TestRecursion小程序的输出结果:

 ok 0 ok 1 ok 2 ok 3 ok 4 ok 5 ok 6 ok 7 ok 8 ok 9 ok 


分析调用过程:fun(10)->fun(9)->fun(8)->fun(7)->fun(6)->fun(5)->fun(4)->fun(3)->fun(2)->fun(1)->fun(0)
我们倒过来分析:当i=0时,首次不满足i>0的条件,所以首先打印“ok"。然后fun(0)结束了,返回到fun(1)中,执行调用fun(0)的下一条语句,即System.out.print(i),此时i=0.肯定有的朋友不明白为什么这里i=0.看下面的代码

public static  void fun(int i){//此时i==1
	if(i > 0){//yes
		i--; //此时i==0了
		fun(i);//即fun(0)
		System.out.print(i);//i==?
	}
	System.out.print(" ok ");
}


继续分析:打印"0",又打印" ok ",之后fun(1)方法结束了,返回到fun(2)调用fun(1)的下一条语句,System.out.print(i),此时i=1,依次类推。

分享到:
评论
4 楼 weiwei14811 2012-08-29  
很不错,
3 楼 Leasen 2012-08-09  
建议楼主看看Inside JVM,看一下执行栈那一段  可能会理解得更深入一点
2 楼 ifox 2012-03-09  
不错啊,我又debug一下。感觉理解效果更好 了
1 楼 java小生 2012-03-07  
Recursion

相关推荐

    递归和循环之间不得不说的故事

    递归直通车帝龟出世寻欢初识帝龟初现端倪来龙去脉迷失的帝龟我要这递归有何用?考考你 帝龟出世 大家好,我是今天的主角,帝龟! 一只自带帝王之气的乌龟殿下 – – wo来自遥远的东海之滨,每天清晨我…咳咳, 有些...

    不得不说的全排列算法递归实现

    不得不说的全排列算法递归实现 我真的是菜啊,留的算法作业几乎没有一次自己写出来过…都是要上网看别人的博客才能懂,自己好笨好菜,

    二叉树的基本操作,包括前序、中序、后序遍历的递归和非递归算法

    二叉树的基本操作,包括前序、中序、后序遍历的递归和非递归算法,不得不下的资源

    pytorch_RVAE:递归变异自动编码器,可生成使用pytorch实现的顺序数据

    男人相信他们不得不走在,因为他们的是昂贵重要 两家公司坚持认为,可以在程序中包含颜色设置 用法 在模型训练之前,有必要训练单词嵌入: $ python train_word_embeddings.py 该脚本训练了定义的单词嵌入 参数: ...

    rdp-generator:递归下降解析器生成器

    在看到许多编程语言类的人编写他们的Wren递归下降分析器,并且不得不为我的编译器类编写此程序之后,我认为我会发布源代码,以便也许有人可以从其生成的代码中受益。 我可能会在生成的代码中添加水印,以便Fenwick...

    使用词嵌入和递归神经网络在情感分析中利用上下文相似性-研究论文

    当今时代充满竞争,在这个竞争中,如果任何组织想要保持相关性,那么他们将不得不对用户的意见给予足够的关注,这就是公司通过利用人工智能和自然语言处理来做的。 但是,这些意见数据只能以具有大量隐藏信息的非...

    TFSUndo-for-TFSAdmins:TFS UNDO 其他结帐 - 对所有用户递归

    因此,在大型组织中,如果您有 100-200 名开发人员在一个分支中工作,这意味着如果 100 名开发人员分别从分支签出 1 个文件,那么我将不得不按 100 次撤消按钮以使分支签出免费。 我进行了广泛的搜索,但找不到...

    C语言学习重难点分析编程经验分享等17个资料合集.zip

    C语言与C++不得不说的那点事.pdf C语言与Java的区别.pdf C语言函数的递归和调用实例分析.pdf C语言单链表功能完全详解.pdf C语言大作业(仅供参考).docx C语言嵌入式系统编程修炼之内存操作.pdf C语言经典算法大全....

    用汇编语言实现汉诺塔问题

    汇编语言中用递归算法实现汉诺塔问题。有X,Y,Z三个柱子和几个大小都不一样且能套进柱子的圆盘(编号为1,2,3,……,N),这N个圆盘已按由大到小的顺序依次套在X柱上,要求将这些圆盘按如下规则由X柱移到Z柱上。 ...

    C语言数据结构第四章实验报告

    2、设计一个递归算法来实现字符串逆序存储,要求不另设串存储空间。 3、设计算法,实现下面函数的功能。函数void insert(char*s, char*t, int pos)将字符串t插入到字符串s中,插入位置为pos。假设分配给字符串s的空间...

    Oracle9i的init.ora参数中文说明

    值范围: 任何有效的日期格式掩码, 但不得超过一个固定长度。 默认值: 派生 nls_timestamp_tz_format: 说明: 与 NLS_TIME_TZ_FORMAT 相似, 其中的一对值指定 TIMESTAMP 数据类型的默认值, 该类型除存储 YEAR, MONTH...

    python学习笔记(八)函数相关

    函数相关 ...能不使用就不使用,只有再不得不使用时才使用(深度优先目录遍历) 实例: 求n的阶乘 求斐波那契数列的第n项 前两项都是1,后面的项的值等前面两项的和 如:1, 1, 2, 3, 5, 8, 13, … 代码实现:

    cps-defun:Coq证明“切出连续性”

    由于Coq的终止检查器的功能不足以证明某些AM的终止,或者不能期望AM总体上终止(lambda calculi的AM /具有循环的语言的AM),因此我们不得不将AM定义为关系。 更准确地说,所有AM均被定义为小步语义。 AM的每个尾部...

    快速创建树的方法 (抛弃拙劣的数据库结构和算法)

    1、现在很多人都使用“父—子结构+递归算法”来显示树型的层次结构,但是不得不说这是一种非常拙劣的方式,下面给大家一种简单方便的数据结构和算法,快速显示树型的层次结构:2、数据库结构例如表“国家”可以是...

    知名公司数据结构笔试题及答案

    13. 递归的折半查找算法[不限语言] 14. 解释一下什么是B+树,如何实现B+树的查找和插入.(用图示) 15.实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数。 13.排序方法比较 (intel) 排序...

    ElementFinder

    这一切都很顺利,直到我意识到 IE8 不支持 #getElementByClass 这使得它变得相当困难,我不得不考虑如何从 DOM 中获取我需要的类(有一次我考虑递归地这样做,有趣的是,这不是最好的策略;)。 这是一个很好的测试...

    向前欧拉法matlab代码--Graduation-Thesis-Code:毕业论文代码

    研究的对象以UR5机械臂为例,采用了标准的DH方法建立了所有的运动学/动力学模型,不得不说的是,当初在编写动力学方程的时候,感受到了标准法的不便之处,不少论文给出的是改进的DH法建立的运动学模型,不过没去验证...

Global site tag (gtag.js) - Google Analytics