
转眼间又到了深夜,终于能好好吃一把鸡了。算法
…………微信
等等,TM11点就停电了。玩鸡毛!!!网络
哦……那么,就只能……学习了……函数
今天学啥呢?学习
对,没错优化
今天要教给你们的是spa
递(zhuang)归(bi)大法.net
本节纲要:3d
- 什么是递归orm
- 递归函数的工做原理
- 经典的递归问题
- 递归的一些适用状况
什么是递归?
在此以前,让老衲来引用一句名言:
迭代的是人,递归的是神
–L. Peter Deutsch
那么,何为递归呢?别急,听老衲慢慢为施主道来。
所谓递归(recursion):
说白了就是子程序(或函数)直接调用本身或间接调用本身的一种基本方法。运用递归一般能够把一个大型复杂的问题层层转化为一个与原问题类似的规模较小的问题来求解,从而减小程序的代码量。
递归调用的形式:
-直接调用:即在函数中调用函数自己。
举个栗子,下面一段代码用于求斐波那契数列的第N项:
- 间接调用:指A函数执行中调用了B函数,而B函数又调用了A函数。
仍是再举个栗子吧。
固然,这是一个死递归,没有出头之日的。
简单介绍了递归,下面开始咱们的重头戏。
递归的工做原理:
- 先谈谈递归函数的内部执行过程:
开始时,系统先为递归调用设立一个工做栈,它的结构包括值参、局部变量和返回地址。
每次执行递归调用时,系统会把递归函数的值参和局部变量的当前值以及调用后的返回地址压栈。
每次递归调用结束后,将栈顶元素出栈,而后转向返回地址指定的位置继续执行。
这里关于栈的内容暂时不过多赘述,你们能够自行上网找资料查询。其实说白了递归调用的本质仍是函数调用,那函数调用必然会遵循一个原则:被调用的函数会复制一个副本,为调用者服务,而不受其余函数的影响。
不少人把递归理解为一种代码反复循环使用。其实这是有失偏颇的。像前面说的,一个函数func被调一次,他就在内存中复制一份代码,再调用,再复制。而后根据内存的栈式管理返回退出。你也能够把被递归调用各个函数看成不一样名的函数,这样更便于理解。
- 下面来结合一个求阶乘的例子来讨论一下这个过程:
先假设咱们在main函数里面传入的num=3吧。
1.一层执行到res=3*factorial(3-1);中止,执行二层factorial (3-1),也就是factorial (2)
2.二层执行到res=2*factorial(2-1);中止,执行三层factorial (2-1),也就是factorial (1)
3.三层执行到if(num==1) res=1;而后return(res)到二层的factorial (2-1)的位置,二 层继续执行
4.二层执行res=1*2;而后就return(res)到一层factorial (3-1)的位置,一层继续执行
5.一层执行res=2*3;而后就return(res)到了最初调用factorial (3)的main函数里。因此就获得结果为6
整个过程大致就是这样的。
函数的执行流程:
递归的经典问题
汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候作了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序从新摆放在另外一根柱子上。而且规定,任什么时候候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操做?
在学习了上面的递归原理以后,这里是否是想动手AC一下这道题呢?
假若有ABC三根柱子,先假设A柱子只有3个盘子的状况。盘子从上到下依次编号为123.咱们能够先把1和2号盘子借助C柱子,移动到B柱子上,而后在将3号盘子移动到C柱子上。而后再借助A柱子,将1和2号盘子移动到C柱子上,done!至于怎么把1和2号盘子借助C移到B柱子上,想必也不用多说。
那么,假若有N个盘子,咱们只须要借助C柱子,将1到N-1号盘子移动到B柱子上,再将N号盘子移动到C上,再将1到N-1号盘子移动到C上,done!而借助C柱子移动1到N-1号盘子到B柱子,又只须要考虑将1到N-2号盘子借助B移到C上,最后再从C里移动回来。这样咱们就不断将问题缩小了。卧槽是否是有点晕,那就对了。
算法描述:
当A柱子只有一个盘子的时候,只须要从将A柱子上的一个盘子移到C塔上。
- 当A柱子上有两个盘子是,先将A柱子上的1号盘子(编号从上到下)移动到B柱子上,再将A柱子上的2号盘子移动的C柱子上,最后将B柱子上的小盘子移动到C柱子上。
- 当A柱子上有3个盘子时,先将A柱子上编号1至2的盘子(共2个)移动到B柱子上(需借助C柱子),而后将A柱子上的3号最大的盘子移动到C柱子,最后将B柱子上的两个盘子借助A塔移动到C柱子上。
- 当A柱子上有n个盘子是,先将A柱子上编号1至n-1的盘子(共n-1个)移动到B柱子上(借助C柱子),而后将A柱子上最大的n号盘子移动到C柱子上,最后将B柱子上的n-1个盘子借助A柱子移动到C柱子上。
综上所述,除了只有一个盘子时不须要借助其余柱子外,其他状况均同样的。
好,又到了激动银心的看代码时间:
关于递归的适用状况:
递归一般用来解决结构自类似的问题。所谓结构自类似,就是说在结构上组成类似的,能够采用同一种方法去解决。具体地,整个问题的解决,能够分为两部分:第一部分是一些特殊状况,有直接的解法;第二部分与原问题类似,但比原问题的规模小。实际上,递归就是分而治之的思想,把大问题化为小问题,再把小问题化为更小的问题,在解决这样一个个的小问题以后,大问题天然迎刃而解。
所以,递归有两个基本要素:
(1)边界条件:肯定递归到什么时候终止,也称为递归出口。
(2)递归模式:大问题是如何分解为小问题的,也称为递归体。递归函数只有具有了这两个要素,才能在有限次计算后得出结果。
-The End-
编辑 / 邓发珩
指导老师 / 秦时明岳
注:部分资料来源网络。做者为优化突击队成员,
若有疑问,欢迎咨询:邓发珩 (华中科技大学本科一年级、联系方式:2638512393@qq.com、我的公众号:程序猿声)秦虎老师(professor.qin@qq.com)
本文分享自微信公众号 - 程序猿声(ProgramDream)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。