​学习之道,重在实践。尤其是像编程这类的技术活,更需要日积月累的实操,不断地试错,发现问题,解决问题。这样一来,编程技术才会真正地有所提升。

因此,C语言学习系列暂时缓一天,做些练习题,让脑子回顾一下之前所学习的内容,也是防止学了新的,忘了旧的。

同时,温故而知新,也可以从旧的知识里面挖掘出新的知识点。

下面就通过练习编程中一道较为经典的题目,来讲一下函数中的递归问题。

兔子数列

兔子数列,又叫斐波那契数列,黄金分割数列。

案例:兔子的繁衍能力是极强的,每 3 个月成熟一次,并会生出 1 对新的小兔子,且之后每个月都会生出 1 对兔子。

前提:兔子开了永生BUFF。

题目:已知有 1 对兔子,求 3 年后,将会拥有多少只兔子?

第一个月,获得了 1 对新生的小兔子。

第二个月,小兔子成熟了,仍然还是 1 对兔子。

第三个月,生了 1 对小兔子,现在是 2 对兔子了。1 对开始繁殖的成熟兔子,1 对小兔子。

第四个月,生了 1 对小兔子,现在是 3 对兔子了。1 对开始繁殖的成熟兔子,1 对还未繁殖的成熟兔子,1对小兔子。

第五个月,生了 2 对小兔子,现在是 5 对兔子。2 对开始繁殖的成熟兔子,1 对还未繁殖的成熟兔子,2 对小兔子。

...

接下来,就是找到其中的规律了。

/*
* 第 1 个月 - 1 对兔子
* 第 2 个月 - 1 对兔子
* 第 3 个月 - 2 对兔子
* 第 4 个月 - 3 对兔子
* 第 5 个月 - 5 对兔子
* ...
* 第 n 个月 - f(n-1)+f(n-2) 对兔子
*/

从第三个月开始,兔子的数量都是前两个月的兔子数量相加的结果。

这里我有两种解题方式,一种是通过 for 循环迭代,一种是使用递归函数。

先来看第一种,用 for循环。

#include<stdio.h>
int main(){// a_count  前两个月的总数// b_count  前一个月的总数// count  当前月的总数int a_count=1, b_count=1, count=0;for(int i=3;i<=36;i++){ // 第三个月开始增长count = a_count + b_count; // 计算当前月的数量// 为了计算下个月的数量,将前两个月额总数都进行替换a_count = b_count;b_count = count;}printf("三年后一共获得%d只兔子。", 2 * count);
}

运行结果:三年后一共获得29860704只兔子。(永生兔子,暴富秘籍!)

第二种,使用递归函数。

#include<stdio.h>
int rabbit(int);
int main(){int count = 0;count = rabbit(36);printf("三年后一共获得%d只兔子。", 2 * count);
}
int rabbit(int n){// 第一个月和第二个月的总数为 1if(n <= 2){return 1;}// 第三个月开始总数等于前两个月的总和return rabbit(n-1)+rabbit(n-2);
}

运行结果:三年后一共获得29860704只兔子。

递归函数相比较循环迭代,整体的代码量要少很多,不需要定义太多的变量。但建议上,还是少用递归函数,这是因为递归函数存在着一个致命缺陷。

下面,来学习一下递归函数。

递归函数

递归,指的是程序调用自身的方法。

递归函数,则是函数自己调用自己。

其主要思想在于化繁为简,大事化小。把一个大型复杂的任务,拆分成一个个小任务进行处理。使用递归,可以用最少的代码解决复杂的问题,大大减少了代码量。

递归和循环迭代很相似,都是重复执行某一段指令,且都需要一个终止条件

如果没有终止条件,那么这个程序可以说是死的,卡在这个位置,一直执行这个部分的内容,后面就再也执行不了。

所以说,不管是循环还是递归,在每次调用之后,都要趋近于终止条件。

但也有一个本质的区别。递归是有去有回,循环迭代是一去不回的。

就比如,在入口处有人给了你一把钥匙,你拿着钥匙打开第一扇门,发现还有一道门,且还可以用这把钥匙打开。

循环迭代,就好比门口的那个人是一路跟着你,每打开一扇门,你就跟他说这是第几扇门。

递归,就像是懒人,只给你钥匙,然后在入口等待。你需要一扇一扇门开到底,然后走回来一遍一遍的数,回到入口处告诉那个人一共有多少扇门。

从上面这个比喻中可以看出,递归存在的一个缺陷,时间开销巨大

循环迭代只要走一遍就可以获得结果,而递归函数需要走过去再走回去,相当于是循环迭代所花费的时间两倍。(实际上就不确定是多少倍。)

同时还有这第二个缺陷,内存开销巨大

拿兔子数列的递归函数举例,假设这里的 n 此时取 5,那么结果返回的值是 rabbit(4)+rabbit(3)。但这不是一个确切的数值,就会暂存在内存中,接着去计算rabbit(4)和rabbit(3)。

直到计算到 rabbit(1) 和 rabbit(2),得到返回值 1,在传回去给前面暂存起来的返回值计算。

而且在运行的这段时间内,前面得到的没有值的返回内容是需要地方暂时存放起来。可想而知,一个递归所需要的内存是得有多大。

而循环迭代,仅是在原本开辟的内存空间里不断对数值进行迭代更新,没有去征用新的内存。

所以一般都是建议程序中能用循环迭代的,尽量用循环迭代。能少用递归的,就少用递归。

总结

使用循环迭代和递归函数的方式实现兔子数列的问题。

递归函数是一种函数自己调用自己的方法,主要思想是将复杂的任务拆分一个个简单的任务分别处理。

递归函数的必要条件是,必须要有一个终止条件,且每次调用都要趋近于终止条件。

但递归函数是一种内存和时间开销都非常巨大的方法,一般建议能用循环迭代用循环,尽可能少用递归函数。

从兔子数列延伸到递归函数的知识相关推荐

  1. 递归函数输出斐波那契数列-黄金分割数列-兔子数列(python)

    递归函数输出斐波那契数列-黄金分割数列-兔子数列(python) 斐波那契数列介绍 数学家莱昂纳 多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔 ...

  2. 兔子数列规律怎么讲_探究“兔子数列”提升数学能力

    倪丽君 [摘 要]在解决问题过程中,教师一般根据问题类型进行模式教学,而建模的过程中,能力的培养则是数学教学的重点.以斐波那契数列的教学为例,通过外在的操作活动,培养学生的数学应用能力,让学生经历从形 ...

  3. 【C语言】案例二十五 兔子数列(斐波那契数列)

    案例描述 兔子数列又称斐波那契数列,黄金分割数列,具体描述如下:一对兔子在出生两个月后,每个月都能生出一对小兔子,现有一对刚出生的兔子,假设所有兔子都不死,那么一年后有对少只兔子? 案例分析 n表示月 ...

  4. php算法求出兔子数列,PHP算法:斐波那契数列的N种算法

    前言 前段时间,遇到优化计算斐波那契数列的常规递归方法,但是一时间并没有及时想到很好的方法,所以后面查找了相关资料,总结了多种计算解法,所以分享出来,和大家一起交流学习. 斐波那契数是什么 斐波那契数 ...

  5. OJ1055: 兔子繁殖问题(C语言计算斐波那契数列/“兔子数列”)

    题目描述 这是一个有趣的古典数学问题,著名意大利数学家Fibonacci曾提出一个问题:有一对小兔子,从出生后第3个月起每个月都生一对兔子.小兔子长到第3个月后每个月又生一对兔子.按此规律,假设没有兔 ...

  6. 兔子数列规律怎么讲_神奇兔子数列

    假设第1个月有1对刚诞生的兔子,第2个月进入成熟期,第3个月开始生育兔子,而1对成熟的兔子每月会生1对兔子,兔子永不死去--那么,由1对初生兔子开始,12个月后会有多少对兔子呢? 兔子数列即斐波那契数 ...

  7. 兔子数列 - C语言

    兔子数列 兔子数列的起源 公元13世纪,在意大利有一位天才的数学家名字叫斐波那契,他在一本<算盘之书>的著作里记载了这样一道数学题:有一对兔子,每一个月可以生下一对小兔子,而且假定小兔子在 ...

  8. 【递推】HDU -2018 母牛的故事斐波那契兔子数列

    函数之递归的应用 母牛的故事 (这个问题还有很多类似的,比如种树,每一年种的树品质在改变,当然区别在于树不能生孩子.. 相应的人类达到法定年龄就可以生孩子,这个和母牛问题一样,只不过时间间隔变化了. ...

  9. 兔子数列(斐波拉契数列)javscript的三种写法

    斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列&qu ...

最新文章

  1. hive-数据倾斜记录分享
  2. 模块化编程AMDCommonJS
  3. 华为SAP解决方案为海澜之家带来新的科技创新
  4. java webservice https_WebService的HTTPS访问——解决PKIX错误 | 字痕随行
  5. CSDN编程挑战——《交替字符串》
  6. 笔记(2015-07-24)
  7. Oracle-11g 基于 NBU 的 rman 冷备份及恢复
  8. 在 MyEclipse 5.1GA 上使用 XFire 编写 Web Service
  9. 三维数学基础(一)坐标系、向量、矩阵
  10. Android未发现目标设备,Android设备不会显示为Unity3d调试的目标
  11. android 智能手机usb驱动程序,华为手机usb驱动下载
  12. AI改变现代商业的25种方式
  13. SQL Server 2019的下载与安装
  14. 如何安装iOS 13 、 macOS Catalina 、watchOS 6 、 tvOS 13 或 iPadOS Beta
  15. stm32 app 连上阿里云
  16. Android版添加phonegap-百度社会化分享插件教程
  17. TCPIP卷一(8):EIGRP的组建和邻居状态机
  18. 永顺一中2021高考成绩查询入口,2017年高考永顺传来喜报
  19. label 标签属性的总结归纳
  20. Python爬虫:史上最详细的Python爬虫库urllib讲解,绝对经典,值得收藏

热门文章

  1. 刘永好旗下华融化学上市:市值71亿 妻女均为外籍
  2. 乘风破浪初心不改,实力出众当红不让
  3. 庄子心得10:心态与状态
  4. 案例精选 | 知乎千万级高性能长连接网关揭秘
  5. 苹果x支持5g吗_期待已久的iphone12系列终于发布,首款支持5G的苹果
  6. 云计算机怎么给学生机安装软件,如何给学生机系统安装软件?
  7. MAC电脑上使用E-Study的坑
  8. 痞子衡嵌入式:我的博客园积分排名终于挤进了前3000名榜单
  9. WEB前端笔记第一天
  10. html5css写旋转立方体,css练习-旋转的立方体