Java中的迭代与递归

小伙伴们注意了!

小编在这里给大家送上关注福利:

搜索微信公众号“速学Java”关注即可领取小编精心准备的资料一份!

1. 递归

考虑阶乘函数:n!=n*(n-1)*(n-2)*…*1

计算阶乘有很多方法。一种方法是n!等于n*(n-1)!因此,程序可以直接写成:

项目1:

为了运行这个程序,计算机需要建立一个乘法链:阶乘(n)→阶乘(n-1)→阶乘(n-2)→…

→! (1)。

因此,计算机必须跟踪后面要执行的乘法。

这种程序的特征是一系列操作,称为递归。

递归可以进一步分为线性递归和树递归。

当跟踪操作链所需的信息量随输入线性增长时,这种递归称为线性递归。

n的计算!

是这样的情况,因为所需的时间随着n线性增长。另一种类型的递归,树递归,当信息量随着输入呈指数增长时发生。

但是我们将在这里不讨论它,稍后再讨论。

2. 迭代

一个不同的角度计算阶乘是首先把1乘以2,然后将结果乘以3,然后除以4,等等,直到n。更正式,程序可以使用一个计数器计数从1到n和计算产品同时,直到计数器超过n。因此,程序可以写成:

项目2:

与程序2相比,这个程序不构建乘法链。

每一步,电脑只需要跟踪产品的当前值和我。这种类型的程序叫做迭代,其状态可以总结为一个固定数量的变量,一个固定的规则,描述了变量应该如何更新,和结束测试指定条件的过程应该终止。

与递归一样,当所需时间随输入线性增长时,我们称之为迭代线性递归。

3. 递归与迭代

通过对这两个过程的比较,我们可以发现它们看起来几乎是一样的,尤其是在数学函数方面。

它们都需要一些与n成比例的步骤来计算n!

另一方面,当我们考虑这两个程序的运行过程时,它们的发展是非常不同的。

在迭代的情况下,程序变量提供了状态的完整描述。

如果我们中途停止计算,恢复计算只需要向计算机提供所有变量。

然而,在递归过程中,信息是由计算机来维护的,因此“隐藏”到程序中。

这使得在停止程序之后几乎不可能恢复程序。

4. 树递归

如上所述,当信息量随输入呈指数增长时,就会发生树递归。

例如,考虑定义如下的斐波那契数列序列:

根据斐波那契数列的定义,斐波那契数列的序列如下:0、1、1、2、3、5、8、13、21、……

递归程序可以立即写成:

项目3:

因此,为了计算fib(5),程序计算fib(4)和fib(3)。

对于计算机fib(4),它计算fib(3)和fib(2)。

注意,fib过程在最后一行调用自己两次。

从定义和程序中可以得到两个观察结果:

第i个斐波那契数列Fib(i)等于(i)/rootsquare(5)四舍五入到最近的整数,这表明斐波那契数列呈指数增长。

这不是计算斐波那契数列的好方法,因为它做了冗余计算。

计算这个过程的运行时间超出了本文的范围,但是在算法书籍中很容易发现,它是O(phi(n))。

因此,程序花费的时间随着输入呈指数增长。

另一方面,我们也可以用迭代的方式编写程序来计算斐波那契数列。

程序4是一个线性迭代。

程序3和程序4所需的时间差别是巨大的,即使是很小的输入。

项目4:

然而,我们不应该认为树递归程序是无用的。

当我们考虑在层次数据结构而不是数字上运行的程序时,树递归是一个自然而强大的工具。

它可以帮助我们理解和设计程序。

与程序3和程序4相比,我们可以很容易地看出程序3更直接,即使效率更低。

在此之后,我们很可能将程序重新规划为迭代的方式。

最后,想学习Java的小伙伴们!

关注“速学java”公众号就可以拿到一份我为大家准备的Java学习资料!

对Java感兴趣的小伙伴也可以加 小编V❤: suxuejava

猜你喜欢

转载自blog.csdn.net/suxue_java/article/details/88355369