热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:递归的逻辑——递归关系模型

本文由编程笔记#小编为大家整理,主要介绍了递归的逻辑——递归关系模型相关的知识,希望对你有一定的参考价值。   查尔斯·巴贝奇是一名19世纪的英国发明家,也被说成是职业数学家。他曾经发明了差分机——一
本文由编程笔记#小编为大家整理,主要介绍了递归的逻辑——递归关系模型相关的知识,希望对你有一定的参考价值。


  查尔斯·巴贝奇是一名19世纪的英国发明家,也被说成是职业数学家。他曾经发明了差分机——一台能够按照设计者的意图,自动处理不同函数的计算过程的机器。这是一台硕大的、泛着微光的金属机器,包括数以千计加工精密的曲柄和齿轮。他在孤军奋战下造出的这台机器,运算精度达到了6位小数,能够算出好几种函数表。此后的实际运用证明,这种机器非常适合于编制航海和天文方面的数学用表。

技术分享图片

  巴贝奇花费了漫长的一生来改进差分机,先是一种设想,然后是另一种设想。他曾设想用储存数据穿孔卡上的指令进行任何数学运算的可能性,并设想了现代计算机所具有的大多数其他特性。然而这些都超越了他所处的时代——巴贝奇的设想直到电子时代才得以完成——改进版的差分机最终没有变成现实。

  在一次科技展览会上,年轻而又光彩照人的奥古斯塔·爱达·拜伦看到了被称为“思考机器”的差分机试验品。那一刻,爱达确定了她一生的目标——完成这台精美的机器。接下来的几年里,爱达迅速学会了各种数学知识并拜入巴贝奇门下,终其一生让处理数的差分机变成处理信息的分析机。

  为了展示机器的威力,爱达曾设计了一个假想的程序,它循环运行,一次迭代的结果将成为下一次迭代的输入,每个函数前后相继,遵循相同的规则,巴贝奇将这个思路称为“机器咬尾巴——团团转”。然而这个程序仅仅存在于爱达的头脑中,直到她去世也没有生产出可以运行这个程序的机器。

  一个世纪后,爱达的梦想终于变成了现实,她的假想也成为程序员们的一种重要算法——递归。


递归关系式

  先来看一个表达式:

技术分享图片

  表达式指出从第3项开始,每一项都是由前两项通过计算得出的,这类表达式就是递归关系式,有时也称为差分方程。为了能从递归关系式计算出序列中的每一项,必须知道序列开始的若干个数,这些数被称为初始条件或初始值。

  由于采取逐步计算的方式可以得到序列各项的值,所以很多时候得到递归关系是本身就是朝解决一个计数问题迈了一大步。有些时候甚至只能依赖递归关系进行计算。


不断繁殖的兔子——递归关系模型

  最著名的递归模型当属斐波那契(Fibonacci)数列,它最早出现在1202年。

  斐波那契提出了一个关于兔子的问题:某一年的年底将一雄一雌两只兔子放进围场中。从第二年一月份开始,这对兔子生下了一双儿女。此后每一对兔子在第二个月都能产下一对龙凤胎。一年后,围场里能有多少对兔子?

  这里的假定条件是不考虑兔子的近亲繁殖问题,也不考虑人类吃货造成的影响,并且每对兔子都能健康成长……简单而言就是不考虑科普,只关注数学模型。


递归表达

  在上一年12月放入一对兔子,次年一月,初始兔子将产下一对新兔子,所以一月份将有两对兔子。二月份,新兔子还没有长大,只有初始兔子能够生产一对兔子,因此二月底将有3对兔子。三月份,初始兔子和1月份诞生的新兔子都将生产一对兔子,再加上二月底本来就有的3对兔子,因此三月底将有2+3=5对兔子:

技术分享图片

  如果令f(n)表示第n-1月末围场中的兔子总对数,那么可以总结出:

技术分享图片

  可以利用这个关系计算出一年后的兔子总对数,即f(13),这需要知道f(1)到f(12)的值:

技术分享图片

  一年后围场中有377对兔子。

  程序通常是从0开始的,因此我们可以令f(0) = 1,这就使得f(2)也满足f(n)的表达式,f(2)=f(1)+f(0),f(0),f(1),f(2),……,f(n)满足递归关系:

技术分享图片

  这个序列就是著名的斐波那契序列,f(0)和f(1)是序列的初始值。

  知道了关系模型后很容易写出一段“机器咬尾巴”的代码:


1 # 用递归计算斐波那契序列
2 def fabo(n):
3 if n <2:
4 return 1
5 else:
6 return fabo(n - 1) + fabo(n - 2)
7
8 if __name__ == __main__:
9 for i in range(2, 14):
10 print(f({0}) = {1}.format(i, fabo(i)))

  打印结果:

技术分享图片


避免无用功

  斐波那契的递归代码很优美,它能够让人以顺序的方式思考,然而这段代码只能作为递归程序的演示样品,并不能应用于实践。在运行时便会发现,当输入大于30时速度会明显变慢,普通家用机甚至无法计算出f(50)。变慢的关键在于每次计算f(n)都要重新求解f(n)前面的所有斐波那契数,相当于做了大量的无用功。

  知道症结后便可以对症下药,只要把所有计算过的数存储起来就能有效改进算法:


1 # 存储所有计算过的斐波那契数
2 fabo_list = [1, 1]
3 # 用递归计算斐波那契序列
4 def fabo_2(n):
5 if n < len(fabo_list):
6 return fabo_list[n]
7 else:
8 fabo_n = fabo_2(n - 1) + fabo_2(n - 2)
9 fabo_list.append(fabo_n)
10
11 return fabo_n
12
13 if __name__ == __main__:
14 for i in range(40, 51):
15 print(f({0}) = {1}.format(i, fabo_2(i)))

  全局变量fabo_list将缓存所有计算过的值,这次可以快速计算f(40)~f(50)的值:

技术分享图片


用循环代替递归

  所有的递归都可以用循环代替,因此递归的实现往往也有对应的循环版本,斐波那契序列也是如此:


1 # 用循环计算斐波那契序列
2 def fabo_3(n):
3 fabo_list = [1] * (n + 1)
4 for i in range(2, n + 1):
5 fabo_list[i] = fabo_list[i - 1] + fabo_list[i - 2]
6
7 return fabo_list[n]
8
9 if __name__ == __main__:
10 for i in range(1, 50):
11 print(f({0}) = {1}.format(i, fabo_3(i)))

  这段代码的运行速度相当快,不仅预存储了所有计算过的斐波那契数,还比fabo_2省去了因递归导致的方法调用的时间。

  所有的递归都可以用循环代替,反过来也一样,所有循环也可以用递归代替,像Erlang这种编程语言,甚至没有定义while、for这种用于循环的语法,全部使用递归。


斐波那契序列的和

  斐波那契序列有很多有趣的性质,其中一个就是求和。

  用S(n)表示前n项的和:

技术分享图片

  先来看一下S(3),利用f(1) = 1,S(3)可以转换为:

技术分享图片

  由此可以大胆地推断:

技术分享图片

  可以用数学归纳法证明这个结论:

  当n=1时,该结论S(1)=f(3)-1=3-1=2,f(0)+f(1)=2,此时结论正确;

  假设结论对于n=t-1成立,t是任意自然数:

技术分享图片

  则当n=t时:

技术分享图片

  由此可见结论是对的,它可以回答图中一共绘制了多少对兔子。

  求和的代码相当简单,不需要傻乎乎的去累加:


1 # 斐波那契序列的前n项之和
2 def fabo_sum(n):
3 return fabo_3(n + 2) - 1

 

  下一篇:递归关系的基本解法

  



   作者:我是8位的


  出处:http://www.cnblogs.com/bigmonkey

  本文以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,非商业用途! 

  扫描二维码关注公众号“我是8位的”

技术分享图片



推荐阅读
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 如何将Python与Excel高效结合:常用操作技巧解析
    本文深入探讨了如何将Python与Excel高效结合,涵盖了一系列实用的操作技巧。文章内容详尽,步骤清晰,注重细节处理,旨在帮助读者掌握Python与Excel之间的无缝对接方法,提升数据处理效率。 ... [详细]
  • 在机器学习领域,深入探讨了概率论与数理统计的基础知识,特别是这些理论在数据挖掘中的应用。文章重点分析了偏差(Bias)与方差(Variance)之间的平衡问题,强调了方差反映了不同训练模型之间的差异,例如在K折交叉验证中,不同模型之间的性能差异显著。此外,还讨论了如何通过优化模型选择和参数调整来有效控制这一平衡,以提高模型的泛化能力。 ... [详细]
  • OpenAI首席执行官Sam Altman展望:人工智能的未来发展方向与挑战
    OpenAI首席执行官Sam Altman展望:人工智能的未来发展方向与挑战 ... [详细]
  • 本文探讨了一种高效的算法,用于生成所有数字(0-9)的六位组合,允许重复使用数字,并确保这些组合的和等于给定的整数N。该算法通过优化搜索策略,显著提高了计算效率,适用于大规模数据处理和组合优化问题。 ... [详细]
  • 遗传算法中选择算子为何置于交叉算子和变异算子之前?本文探讨了这一问题,并详细介绍了遗传算法中常用的选择算子类型及其作用机制。此外,还分析了不同选择算子对算法性能的影响,为实际应用提供了理论依据。 ... [详细]
  • 在《数字图像处理及应用(MATLAB)第4章》中,详细探讨了“逢七必过”游戏规则的实现方法,并结合数字图像处理技术进行了深入分析。本章通过丰富的实例和代码示例,展示了如何利用MATLAB实现这一游戏规则,并介绍了数字图像处理的基本原理和技术应用。内容涵盖了图像增强、滤波、边缘检测等多个方面,为读者提供了全面的技术支持和实践指导。 ... [详细]
  • 探讨 OpenCV 和 Matlab 在最小二乘法直线拟合中的结果差异及原因分析
    在使用最小二乘法进行直线拟合时,OpenCV和Matlab的计算结果存在显著差异。通过详细分析发现,这种不一致性可能源于两种软件在算法实现、数据处理方式以及数值稳定性上的不同。进一步研究还表明,输入数据的格式和预处理步骤也可能对最终结果产生影响。为了确保结果的一致性和准确性,建议在实际应用中对这两种工具的输出进行对比验证,并选择最适合具体应用场景的方法。 ... [详细]
  • 二分查找算法详解与应用分析:本文深入探讨了二分查找算法的实现细节及其在实际问题中的应用。通过定义 `binary_search` 函数,详细介绍了算法的逻辑流程,包括初始化上下界、循环条件以及中间值的计算方法。此外,还讨论了该算法的时间复杂度和空间复杂度,并提供了多个应用场景示例,帮助读者更好地理解和掌握这一高效查找技术。 ... [详细]
  • 本文深入解析了JDK 8中HashMap的源代码,重点探讨了put方法的工作机制及其内部参数的设定原理。HashMap允许键和值为null,但键为null的情况只能出现一次,因为null键在内部通过索引0进行存储。文章详细分析了capacity(容量)、size(大小)、loadFactor(加载因子)以及红黑树转换阈值的设定原则,帮助读者更好地理解HashMap的高效实现和性能优化策略。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 泰波那契数列与斐波那契数列类似,但其计算方法有所不同。本文详细解析了如何高效计算第 N 个泰波那契数,并提供了一种基于动态规划的优化算法。通过使用数组记录中间结果,避免了重复计算,显著提高了算法的执行效率。代码示例展示了具体的实现方法,帮助读者更好地理解和应用这一算法。 ... [详细]
  • 本文详细探讨了Oracle数据库中Number和Float数据类型的特性和使用方法。通过对比分析,解释了Number类型在精度和范围上的优势,以及Float类型在处理科学计算时的灵活性。文章还介绍了Number数据类型的语法结构及其在实际应用中的最佳实践,帮助读者更好地理解和选择合适的数据类型以满足不同的业务需求。 ... [详细]
  • 数字图书馆近期展出了一批精选的Linux经典著作,这些书籍虽然部分较为陈旧,但依然具有重要的参考价值。如需转载相关内容,请务必注明来源:小文论坛(http://www.xiaowenbbs.com)。 ... [详细]
  • 本文探讨了如何在C#应用程序中通过选择ComboBox项从MySQL数据库中检索数据值。具体介绍了在事件处理方法 `comboBox2_SelectedIndexChanged` 中可能出现的常见错误,并提供了详细的解决方案和优化建议,以确保数据能够正确且高效地从数据库中读取并显示在界面上。此外,还讨论了连接字符串的配置、SQL查询语句的编写以及异常处理的最佳实践,帮助开发者避免常见的陷阱并提高代码的健壮性。 ... [详细]
author-avatar
手机用户2602921033
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有