`
543089122
  • 浏览: 149700 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

关于递归和尾递归的原理

阅读更多

基础很重要,这是永远不变的真理。
package sunfa;

public class DiGui {
	public static void main(String[] args) {
		Stack<Integer> stack = new Stack<Integer>(5);
		for (int i = 0; i < 5; i++) {
			stack.push(i);
		}
		System.out.println("dg:");
		dg(stack);
		System.out.println("jc:");
		System.out.println(jc(10));
		System.gc();
		System.out.println("wjc:");
		int r = 1;
		System.out.println(wjc(10, r));
	}

	/*
	 * 要求:栈内的元素要求从栈底开始打印。
	 * 
	 * 递归编程涉及到栈,也就是说比如一个函数在执行的时候遇到了一个递归函数,那么它执行完了该递归函数后必须会执行递归函数后门的代码,
	 * 反过来说就是这个递归函数后面的代码必须在该递归函数执行完了后才能得到执行。
	 * 
	 * 原理:一个函数执行过程中遇到递归(可能是自己或别人的),那么它后面的代码会进行入栈处理,如果这句入栈的代码是这个函数的
	 * 最后一句代码,那它肯定就只能最后被执行了。
	 * 
	 * 用途:比如并查集的路径压缩、平衡二叉树的系列的路径修复(下面的元素通过旋转往上升)都是基于递归的这个特点的。
	 */
	private static void dg(Stack<Integer> stack) {
		if (stack.count() > 0) {
			Object o = stack.poll();
			dg(stack);
			System.out.println(o);
		}
	}
	private static void fdg(Stack<Integer> stack) {
		while (stack.count() > 0) {
			Object o = stack.poll();
			dg(stack);
			System.out.println(o);
		}
	}
	/*
	 * 普通递归:
	 * jc(5)==>
	 * 5*jc(4)--->表达式入栈
	 * 5*4*jc(3)--->上一步的jc(4)是递归表达式,所以此处要先对其进行出栈,计算完jc(4)=4*jc(3)后在将表达式4*jc(3)入栈
	 * 5*4*3*jc(2)--->同上
	 * 5*4*3*2*jc(1)--->同上
	 * 5*4*3*2*jc(1)  ==>由于n=1的时候函数返回的是一个常数1,这个时候表达式变成5*4*3*2*1,不含有任何函数了,
	 * 所以开始计算该表达式的结果,计算结果的过程也是一个出栈并计算的过程。
	 */
	private static int jc(int n) {
		if (n == 1)
			return 1;
		return n * jc(n - 1);
	}

	/*
	 * 尾递归:
	 * wjc(5,1)==>
	 * wjc(4,5)
	 * wjc(3,20)
	 * wjc(2,60)
	 * wjc(1,120)
	 * 尾递归是把每一步的结果都计算好了,所以不存在表达式入栈的缺点。
	 * 
	 * 很明显,普通递归并没有计算每一步的结果,而是到最后一步才去计算的, 它的每一步都包含一个表达式,这个表达式
	 * 用栈来存放,当然栈顶的肯定是一个表达式,所以每一步生成的表达式入栈后到下一步的时候把栈顶的表达式出栈,并解该
	 * 表达式,一直如此直到栈内不存在函数,这个时候才开始计算,如果没有退出条件或因为栈已满了那就会栈溢出。
	 * 
	 */
	private static int wjc(int n, int r) {
		return n == 1 ? r : wjc(n - 1, r * n);
	}
}
5
1
分享到:
评论
3 楼 a346063587 2011-10-26  
嗯。。的确,基础很重要!
2 楼 zhufeng1981 2011-10-26  
huoyj 写道
基础很重要,这是永远不变的真理。 很赞同这句话

很赞同。
1 楼 huoyj 2011-10-26  
基础很重要,这是永远不变的真理。 很赞同这句话

相关推荐

    关于尾递归和Cooper变换

    这是一个关于尾递归和Cooper变换的文档,有兴趣的人可以下载。

    Python尾递归优化实现代码及原理详解

    在尾递归中,先执行某部分的计算,然后开始调用递归,所以你可以得到当前的计算结果,而这个结果也将作为参数传入下一次递归。这也就是说函数调用出现在调用者函数的尾部,因为是尾部,所以其有一个优越于传统递归之...

    Python递归及尾递归优化操作实例分析

    主要介绍了Python递归及尾递归优化操作,结合实例形式分析了Python递归及尾递归优化相关概念、原理、应用与操作技巧,需要的朋友可以参考下

    es6函数之尾递归用法实例分析

    主要介绍了es6函数之尾递归用法,结合实例形式分析了es6函数尾递归原理、用法及操作注意事项,需要的朋友可以参考下

    python中尾递归用法实例详解

    如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。尾递归函数的特点是在...

    JS尾递归的实现方法及代码优化技巧

    主要介绍了JS尾递归的实现方法及代码优化技巧,结合实例形式分析了尾递归的原理、JS实现方法及优化技巧,需要的朋友可以参考下

    美国..现代编译原理C语言描述.高清版

    15.6 高效的尾递归 235 15.7 懒惰计算 236 15.7.1 传名调用计算 237 15.7.2 按需调用 238 15.7.3 懒惰程序的计算 239 15.7.4 懒惰函数式程序的优化 239 15.7.5 严格性分析 241 推荐阅读 243 程序设计:编译函数式...

    prolog教程

    尾递归 135 第17章-自然语言 139 差异表 142 寻找nani 147 Definite Clasue Grammar(DCG) 153 读入句子 155 第18章 C语言调用Prolog Amzi逻辑服务器 159 第19章 Prolog调用C语言 - 以扩展谓词为例 166 定义扩展谓词 ...

    scala-fmi-2019:索非亚大学教授的Scala函数式编程课程材料

    使用Scala进行高级功能编程讲课[] 函数式编程的简要历史为什么选择Scala? Scala作为SCalable语言。 样例代码安装和工具你好,世界测验[]...尾递归不变性持久数据结构( List , Vector ,...) 函数类型,函数文字(la

    C#,归并排序算法(Merge Sort Algorithm)的源代码及数据可视化

    因为使用了递归算法,不能用于大数据的排序。归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;...

    算法导论(part1)

    ·读者需要有一些程序设计方面的经验,尤其需要理解递归过程和简单的数据结构,如数组和链表。 ·读者应该能较为熟练地利用数学归纳法进行证明。书中有一些内容要求读者具备初等微积分方面的知识。除此之外,本书的...

    决策树DTC数据分析及鸢尾数据集分析.doc

    它采用 自顶向下的递归方式,在决策树的内部节点进行属性的比较,并根据不同属性值判断从 该节点向下的分支,在决策树的叶节点得到结论。 决策树算法根据数据的属性采用树状结构建立决策模型, 决策树模型常用来解决...

    python入门到高级全栈工程师培训 第3期 附课件代码

    06 函数式编程尾递归调用优化 07 map函数 08 map函数filter函数 09 reduce函数 10 map reduce filter总结 11 内置函数part1 第17章 01 课前吹牛 02 zip方法 03 max和min高级使用 04 其他内置函数 05 文件操作的...

    算法导论(part2)

    ·读者需要有一些程序设计方面的经验,尤其需要理解递归过程和简单的数据结构,如数组和链表。 ·读者应该能较为熟练地利用数学归纳法进行证明。书中有一些内容要求读者具备初等微积分方面的知识。除此之外,本书的...

    leetcode跳动问题-leetcode-js:leetcode问题的解决方案(在javascript中),每个问题的时间复杂度都超过90+

    用尾递归算法解决问题 问题 28. 实现 strStr() 实现KMP算法 问题 30 连接所有单词的子串 提高效率,现在使用 DFS 问题 35 搜索插入位置 搞清楚原理 问题 44 通配符匹配 实施自下而上的动态规划,目前超过 54%/20% ...

    Lisa:一个简单的 lisp 实现

    丽莎 一个简单的 lisp 实现。 这是一个功能有限的教育项目。 主要目的是了解函数式编程的基本原理——尤其是 lisps,以及编译器理论。...尾递归 垃圾收集 用户定义类型 即时编译器 宏 列出文字 池分配 静态类型

    数据挖掘论文合集-242篇(part2)

    一类递归RBF神经网络模型的稳定性讨论.pdf 不确定性线性系统模型处理的一种新方法.pdf 中介粗集及其在数据挖掘中的应用.caj 二进神经网络隐元数目最小上界研究.pdf 以地物识别和分类为目标的高光谱数据挖掘.caj 信息...

    TheAlgorithms-Python:算法Python

    然后,使用不同的排序算法或通过递归应用存储桶排序算法分别对每个存储桶进行排序。 特性 最差情况下的性能O(n 2 ) 最佳情况下的性能O(n + k) 平均案例表现O(n + k) 资料来源: 鸡尾酒摇床 鸡尾酒摇床...

    UNIX 高级教程系统技术内幕

    第15 章 进一步关于内存管理的主题(413) 15.1 简介 15.2 Mach 的内存管理设计 15.2.1 设计目标 15.2.2 编程接口 15.2.3 基本抽象概念 15.3 共享内存设施 15.3.1 copy-on-write 共享 15.3.2 读写共享 15.4 内存对象和...

Global site tag (gtag.js) - Google Analytics