递归算法

1.递归算法

递归在计算机科学中也称为递归算法。一些问题在分解的时候会有这样的现象:解决该问题的过程是由重复的相似子过程组成,类似这样的问题我们都可以通过递归算法进行解决。在计算机语言中,递归算法的实现靠函数的自我调用来完成,我们所见到的大多数高级编程语言都支持这样的做法。

递归算法通常有两种方式实现——普通递归和尾递归。递归方法简单的来说就是方法的内部再次调用自身,递归方法会嵌套的参与运算。这样每一个递归方法都要分配一个函数堆栈进行操作,这就是普通递归。普通递归对内存的消耗是非常大的。

另一种递归方式被称为尾递归,尾递归对普通递归进行了优化。如果使用尾递归,需要将递归方式进行特殊的设计,它需要将递归方法在return语句后进行单独调用(即尾调用)。当采用尾递归的时候,一些编程语言会进行优化,将所有嵌套的递归方法放在同一个函数堆栈中进行,效率非常快。作为一名Java程序员,如果你无法将递归方法设计成尾递归的模式也没有任何问题,因为Java并没有对尾递归进行优化 ,Java对内存的优化是依赖于回收机制。但是如果你是一名C程序员,就需要对尾递归的写法进行掌握了。

递归算法的优缺点是非常明显,算法实现简单、可读性强是递归算法的优点所在。缺点也同样明显,递归算法会占用大量内存空间,如果递归深度过大,容易发生内存相关问题。所以在递归算法中,有这样一句话:不用递归累死,滥用递归慢死。如何合理的使用递归算法,是递归使用的关键问题。

2.怎么使用递归

在设计递归算法的时候,一定要注意两点:1、设计出等价的递归公式。这一点需要我们拥有一些数学基础以及抽象概括能力,能够在复杂的运行过程中,抽象出等价的函数关系。

2、递归退出的条件。这一点尤为重要,如果递归方法没有结束条件,就如同死循环一样,让内存和CPU直接"撑爆"。常见的递归练习方法有斐波那契数列和汉诺塔移动算法。

2.1 斐波那契数列(Fibonacci sequence)

斐波那契数列是经典的递归算法应用,它是一组有规律数列:"1,1,2,3,5,8,13……",当我们要获取数列中第n位的数字时,可以总结如下公式:

当n=1或者2时,有f(n)=1,当>=3时,有f(n)=f(n-1)+f(n-2)

下面我们要设计一个方法,输出数列的前n位的信息,n通过整型参数控制。如果我们需要一个完整的数列,就需要创建一个数列容器,将数列中的每一位数字依次计算出来,并保存到容器中,最后按照顺序从容器中输出数列(如下列Java示例):

使用数组保存斐波那契数列

采用上面的做法好处非常明显,它能够记录每一位数列的值。当我们需要获取整个数列的时候,这样的方式是可取的。在一些时候,我们只想获取其中一位的数值,我们就不需要记录数列,这个时候使用递归的方式就非常方便(如下Java示例所示):

采用上述代码,可以直接获取到数列中第n位的数值。我们可以发现,使用递归的方式让代码更简洁、阅读起来更友好。下面我们创建两个测试方法,对上述两种方式进行测试:

运行结果:

2.2 汉诺塔(Hanoi)

汉诺塔是一种有趣的益智游戏,很多人在儿时都玩过这种类似的玩具(如下图所示):

汉诺塔

汉诺塔的移动规则是将所有圆盘从A柱移动到C柱上,并保持上小、下大的有序顺序摆放。在移动的过程中,也需要保持这个规则。例如上图的三层汉诺塔,我们在移动的时候有如下步骤(如下图所示):

三层汉诺塔移动步骤

如果有多个盘子,我们设盘子总数为n,我们可以分为两部分解决,一部分是上面的n-1个盘子,它们作为一个整体,另一部分是最下面的盘子n。它们移动可以分为三步:

1.将第一部分的n-1个盘子的作为一个整体,从A移动到B柱上,C柱过度。

2.接着将第n个盘子从A柱移动到C柱上。

3.再将n-1个盘子的整体从B柱移动到C柱上,A柱过度(移动规律如下图所示)。

N个盘子移动时的规律总结

用代码实现的时候,我们就可以利用递归的方式进行移动。下面代码中,我们为了观察移动过程中,各柱子上盘子的变化情况,我们用队列来模拟柱子(实现代码如下所示):

运行结果:

3.递归对循环的替代

在程序开发过程中,很多循环方法都可以使用递归来完成,例如数字的累加和阶层的计算(如下面代码所示)。

运行结果:

在上述示例代码中,我们用递归和非递归两种方式解决了累加、阶乘的循环问题。除此之外,在一些数据结构算法中,递归的使用也非常多,比如二叉树的遍历、排序等。在下面的示例中,我们使用递归的方法进行冒泡排序。

示例运行效果:

传统的冒泡排序需要借助双层循环进行排序交换。如果使用递归的方式,可以减少一层循环。在实际的排序中,我们是不推荐使用递归进行排序的,上述示例仅作为递归算法的一种思考。

java斐波那切数列_Java中的递归方法相关推荐

  1. java斐波那切数列_如何用java语言输出斐波那契数列

    展开全部 Java编程:三种方法实现斐波那契数列 其一方法:public class Demo2 { // 定义三个变量方法 public static void main(String[] args ...

  2. java判断斐波那契数列_Java 实例 - 斐波那契数列

    Java 实例 - 斐波那契数列 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597, ...

  3. 辛星Java动态规划教程第一篇:求斐波那切数列

    对于理解动态规划来说,最简单的题目还是求斐波那切数列的第i个值.很多资料都把它作为一个印子,以此来介绍动态规划的基本定义. 不过也有些书认为菲波那切数列过于简单,以致于不能让读者感受到动态规划的优美之 ...

  4. 【斐波那切数列】LeetCode 70. Climbing Stairs

    LeetCode 70. Climbing Stairs 这是一道利用斐波那切数列求解的题目.求斐波那切数列有比较经典的4种方法 (1)递归法:复杂度太高 (2)迭代法:时间复杂度为O(n)O(n)O ...

  5. 剑指offer——面试题9:求斐波那切数列的四种方法

    剑指offer--面试题9:求斐波那切数列的四种方法 另一个相关的链接:https://blog.csdn.net/Allenlzcoder/article/details/80297333 总结下求 ...

  6. C语言-递归法求斐波拉切数列

    目录 1 斐波拉契数列 1 斐波拉契数列 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子 ...

  7. 菲波那切数列案例演示(递归方法)

    /** * 功能:菲波那切数列案例演示(递归方法) * 详情:斐波那契数,亦称之为斐波那契数列(意大利语: * Successione di Fibonacci),又称黄金分割数列.费 * 波那西数列 ...

  8. JAVA中打印斐波拉契数列_java打印斐波那契数列

    每行 5 个,输出斐波那契数列的前 20 个数字 6. 编写程序接受用户输入一个... 3 ? 这一公式输出斐波那契数列中的前 40 个数. 保存文件名为:bnds11.java class bnds ...

  9. java斐波那契 递归_Java递归实现斐波那契数列

    程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一 ...

最新文章

  1. 小程序客服自动回复图片,云开发的实现
  2. 小程序云开发,判断数据库表的两个字段匹配 云开发数据库匹配之 and 和 or 的配合使用
  3. angular $observe() 和$watch的区别
  4. SpringCloud系列十二:SpringCloudSleuth(SpringCloudSleuth 简介、SpringCloudSleuth 基本配置、数据采集)...
  5. python导入不在同一路径的函数_Python小课堂|模块
  6. (王道408考研操作系统)第一章计算机系统概述-第一节1:操作系统基本概念以及目标和功能
  7. 数据库每日一题 2020.04.29
  8. c语言语句的使用形式,C语言如何使用print语句
  9. css 30 常用选择选择器
  10. android黑名单挂断电话(endCall)反射方法获取
  11. 建立民间贷款集资合法化
  12. Mac-wifi密码破解 2020-04-30
  13. Dojo Shifter 2 for Mac(ae效果图层处理插件)
  14. 卡方检验python程序_卡方检验及其python实现
  15. 何谓Palm size-PC及Pocket PC?
  16. 端口碰撞Port Knocking和单数据包授权SPA
  17. BCD码和ASCII码的相互转换
  18. 企业生产中,APS系统有哪些具体应用场景?
  19. 数理统计内容整理(一)基本概念
  20. 基于哈工大LTP句子主干提取

热门文章

  1. vb.net读取excel并写入dgv_如何用Python读取Excel中的图片?然后写入图片?
  2. 《集体智慧编程》数学公式
  3. python爬虫登陆网页版腾讯课堂
  4. 给书配代码-电力经济调度(1):基于拉格朗日及运筹规划方法的经济调度算法
  5. 36篇博文带你学完opencv :python+opencv进阶版学习笔记目录
  6. Windows下solr的安装与部署
  7. JavaScript实现detectUndirectedCycle检测无向循环算法(附完整源码)
  8. OpenCASCADE绘制测试线束:数据交换命令之XDE 形状命令
  9. wxWidgets:wxInfoBar类用法
  10. boost::type_erasure::relaxed相关的测试程序