Java中的迭代与递归
递归
提到迭代,不得不提一个数学表达式: n!=n*(n-1)*(n-2)*...*1
有很多方法来计算阶乘。有一定数学基础的人都知道n!=n*(n-1)!因此,代码的实现可以直接写成:
代码一
int factorial (int n) {
if (n == 1) {
return 1;
} else {
return n*factorial(n-1);
}
}
在执行以上代码的时候,其实机器是要执行一系列乘法的: factorial(n) → factorial(n-1) → factorial(n-2) → ... → factorial(1)。所以,需要不断的跟踪(跟踪上次计算的结果)并调用乘法进行计算(构建一个乘法链)。这类不断调用自身的运算形式称之为 递归 。递归可以进一步的分为线性递归和数形递归。信息量随着算法的输入呈线性增长的递归称之为线性递归。计算n!(阶乘)就是线性递归。因为随着N的增大,计算所需的时间呈线性增长。另外一种信息量随着输入的增长而进行指数增长的称之为树形递归。
迭代
另外一种计算n!的方式是:先计算1乘以2,然后用其结果乘以3,再用的到的结果乘以4....一直乘到N。在程序实现时,可以定义一个计数器,每进行一次乘法,计数器都自增一次,直到计数器的值等于N截至。代码如下:
代码二
int factorial (int n) {
int product = 1;
for(int i=2; i<n; i++) {
product *= i;
}
return product;
}
和代码一相比,代码二没有构建一个乘法链。在进行每一步计算时,只需要知道当前结果(product)和i的值就可以了。这种计算形式称之为迭代。迭代有这样几个条件:1、有一个有初始值的变量。2、一个说明变量值如何更新的规则。3、一个结束条件。( 循环三要素:循环变量、循环体和循环终止条件 )。和递归一样。时间要求随着输入的增长呈线性的可以叫做线性迭代。
迭代 VS 递归
比较了两个程序,我们可以发现,他们看起来几乎相同,特别是其数学函数方面。在计算n!的时候,他们的计算步数都是和n的值成正比的。但是,如果我们站在程序的角度,考虑他们是如何运行的话,那么这两个算法就有很大不同了。
(注:原文中关于其区别写的有点扯,这里就不翻译了,下面是笔者自己总结内容。)
首先分析递归,其实递归最大的有点就是把一个复杂的算法分解成若干相同的可重复的步骤。所以,使用递归实现一个计算逻辑往往只需要很短的代码就能解决,并且这样的代码也比较容易理解。但是,递归就意味着大量的函数调用。函数调用的局部状态之所以用栈来记录的。所以,这样就可能浪费大量的空间,如果递归太深的话还有可能导致堆栈溢出。
接下来分析迭代。其实,递归都可以用迭代来代替。但是相对于递归的简单易懂,迭代就比较生硬难懂了。尤其是遇到一个比较复杂的场景的时候。但是,代码的难以理解带来的有点也比较明显。迭代的效率比递归要高,并且在空间消耗上也比较小。
递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换。
能用迭代的不要用递归,递归调用函数不仅浪费空间,如果递归太深的话还容易造成堆栈的溢出。
数形递归
前面介绍过,树递归随输入的增长的信息量呈指数级增长。比较典型的就是斐波那契数列:
用文字描述就是斐波那契数列中前两个数字的和等于第三个数字:0,1,1,2,3,5,8,13,21......
递归实现代码如下:
int fib (int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}
计算过程中,为了计算fib(5),程序要先计算fib(4) 和 fib(3),要想计算fib(4) ,程序同样需要先计算 fib(3) 和 fib(2)。在这个过程中计算了两次fib(3)。
从上面分析的计算过程可以得出一个结论:使用递归实现斐波那契数列存在冗余计算。
就像上面提到的,可以用递归的算法一般都能用迭代实现,斐波那契数列的计算也一样。
int fib (int n) {
int fib = 0;
int a = 1;
for(int i=0; i<n; i++) {
int temp = fib;
fib = fib + a;
a = temp;
}
return fib;
}
虽然使用递归的方式会有冗余计算,可以用迭代来代替。但是这并不表明递归可以完全被取代。因为递归有更好的可读性。
为了让学习变得轻松、高效,今天给大家免费分享一套Java教学资源。帮助大家在成为Java架构师的道路上披荆斩棘。需要资料的欢迎加入学习交流群:9285,05736
Java中的迭代与递归相关推荐
- java中的迭代和递归
迭代和递归 递归是重复调用函数自身实现循环, 迭代是函数内某段代码实现循环.递归总体来说更容易理解,代码简 洁 ,但 是很容易栈溢出,并且费时,迭代的话,代码看起来不是很好理解,但是运行速度快. 场景 ...
- java递归和迭代_Java中的迭代与递归
递归 提到迭代,不得不提一个数学表达式: n!=n*(n-1)*(n-2)*...*1 有很多方法来计算阶乘.有肯定数学基础的人都知道n!=n*(n-1)!因而,代码的实现可以直接写成: 代码一 in ...
- Java中的堆栈安全递归
在本文中,摘自< Java中的函数式编程 >一书,我解释了如何使用递归,同时避免了StackOverflow异常的风险. Corecursion正在使用第一步的输出作为下一步的输入来构成计 ...
- java中的迭代是什么意思_JAVA里的 迭代 具体是指什么意思
JAVA里的 迭代 具体是指什么意思 (2009-10-15 14:30:21) 标签: it 迭代器模式(Iterator pattern) 一. 引言 迭代这个名词对于熟悉Java的人来说绝对不陌 ...
- Java中的无限层级递归树前后端操作解决方案
引言: 抖音真是一个神奇的软件,前两天脑海中浮现了一首歌,知道歌曲的调调,今天打算写博客之前刷了一下抖音,抖音的推荐算法居然给我推送了这首歌,这首歌叫做<一开始说陪你到老的人现在他还好吗> ...
- Java中的异常和递归
(一)HashMap (1)HashMap集合本身基于哈希表 它可以保证键的唯一性(Map都是针对键有效) HashMap<String,String> String:人的ID编号 Str ...
- java中的迭代是什么意思_java迭代指的是什么意思
java迭代指的是什么意思 发布时间:2020-11-10 10:54:42 来源:亿速云 阅读:74 作者:小新 这篇文章主要介绍java迭代指的是什么意思,文中介绍的非常详细,具有一定的参考价值, ...
- java中的递归算法_java递归实现
二话不说,先上代码 Java代码 publicclassTestRecursion{ //递归方法 publicstaticvoidfun(inti){ if(i >0){ i--; fun(i ...
- java 中序遍历(递归、堆栈)
递归 源代码: //中序遍历--递归public void theFirstTraversal(Node n){if(n.getLeftNode()!=null)theFirstTraversal(n ...
最新文章
- 神经网络中参数数量的计算
- Hibernate 、多表关联映射-组件关联映射(component)
- 使用nodejs构建Docker image最佳实践
- micropython 蓝牙音箱_你愿意用ESPY-core做哪些有趣尝试?
- 优达学城深度学习之一——Anaconda
- 媲美专业相机? 看看华为P40带来的影像新突破!
- Centos 6 之samba 搭建
- [网路]Pads 2007常见问题备份解答
- MySQL 索引原理
- 电子计算机上total,计算器频幕上grand total 什么意思
- 据说99%的程序猿都不懂得这样表白
- 使用ffmpeg实现图像格式转换
- [矩阵论] Unit 6. 矩阵的 Kronecker 积与 Hadamard 积 - 知识点整理
- IBM研究院院长:量子计算“大爆发”将在十年内到来
- 浪潮存储与虚拟服务器连接失败,浪潮-异构虚拟化存储研究(示例代码)
- 字符转详细与初步了解for循环
- c++中this指针的理解(转载:苦涩的茶 ——产品开发 C++类中this指针的理解)
- 华为网络配置(OSPF)
- 翻煎饼 swustoj 254
- vue如何监听多个input框_vue中两个input框输入值,自动计算总和到另一个Input框,怎么实现...
热门文章
- Leetcode--96. 不同的二叉搜索树(java)
- 【剑指offer】面试题10- I:斐波那契数列(Java)
- 【剑指offer】面试题55 - II:平衡二叉树(Java)
- 【剑指offer】面试题26: 树的子结构(Java)
- linux cache buffer区别,Linux buffer/cache异同
- java用户注册代码解析_java springmvc 注册中央调度器代码解析
- python百钱买百鸡问题答案_PHP/Python---百钱百鸡简单实现及优化
- 判断三个数是否能构成三角形_三角形的面积
- r3 4300u r5 u_R5刀粒
- Verilog HDL语言实现ROM、RAM+有限状态机