深究递归和迭代的区别、联系、优缺点及实例对比
上一篇 / 下一篇 2012-08-23 09:50:02 / 个人分类:C++
,V'w.~T-b[0 1、概念区分
%a GZ|%J'uS00w)e)@}"v.vi"it%J0 递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己。51Testing软件测试网 V L/R2~ce0d_ s
51Testing软件测试网5c$g;i;S _ Y K;QA,i一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量。递归的能力在于用有限的语句来定义对象的无限集合。
y%{$mQ~-\u0}I0 51Testing软件测试网8\*F-Zu uG;s'Y使用递归要注意的有两点:
i4x(QY/yD"aEA08T(`]`%g V$x0 1)递归就是在过程或函数里面调用自身;51Testing软件测试网C!@%\k R!]8Q`
51Testing软件测试网#\9A!bf t3Sm'z2)在使用递归时,必须有一个明确的递归结束条件,称为递归出口。
cER'j:n"OU;w-F0 51Testing软件测试网Ni~Y!`递归分为两个阶段:51Testing软件测试网wN'`+bqH0uJ
a7]DR6g~F YD0 1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解;51Testing软件测试网wad9RP
`-a+nPd7Y)z:o's&R0 2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解。51Testing软件测试网$m~)LI4e9v
4?CbRK YO0 利用递归可以解决很多问题:如背包问题,汉诺塔问题,...等。51Testing软件测试网1S9Ybr'\ n,[|p"T0b
51Testing软件测试网? J A!hPB ]Ytz7Y斐波那契数列为:0,1,1,2,3,5...
mth"F.hL2]MkjS0 51Testing软件测试网Tn9h? V由于递归引起一系列的函数调用,并且有可能会有一系列的重复计算,递归算法的执行效率相对较低。
V~5p&?l06]svgM4{0 迭代:利用变量的原值推算出变量的一个新值。如果递归是自己调用自己的话,迭代就是A不停的调用B。
3Eb6J Gw!JS8{0D2`0`rOJ-M0 2、辩证看递归和迭代
i5vKZ!R)\"o#vM]8J0 51Testing软件测试网G$S6z6OVV}所谓递归,简而言之就是应用程序自身调用自身,以实现层次数据结构的查询和访问。递归的使用可以使代码更简洁清晰,可读性更好(对于初学者到不见得),但由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。51Testing软件测试网p(g7y,mz!t9W
51Testing软件测试网 j6g C Y d,c7~往往有这样的观点:能不用递归就不用递归,递归都可以用迭代来代替。51Testing软件测试网.D$O.uiu-f)C-zg\
z0o+\"tZ q7z0 诚然,在理论上,递归和迭代在时间复杂度方面是等价的(在不考虑函数调用开销和函数调用产生的堆栈开销),但实际上递归确实效率比迭代低,既然这样,递归没有任何优势,那么是不是就,没有使用递归的必要了,那递归的存在有何意义呢?51Testing软件测试网[m}/|/A.t!T
*y:|g(`#{Dm.bJ0 万物的存在是需要时间的检验的,递归没有被历史所埋没,即有存在的理由。从理论上说,所有的递归函数都可以转换为迭代函数,反之亦然,然而代价 通常都是比较高的。但从算法结构来说,递归声明的结构并不总能够转换为迭代结构,原因在于结构的引申本身属于递归的概念,用迭代的方法在设计初期根本无法 实现,这就像动多态的东西并不总是可以用静多态的方法实现一样。这也是为什么在结构设计时,通常采用递归的方式而不是采用迭代的方式的原因,一个极典型的 例子类似于链表,使用递归定义及其简单,但对于内存定义(数组方式)其定义及调用处理说明就变得很晦涩,尤其是在遇到环链、图、网格等问题时,使用迭代方 式从描述到实现上都变得不现实。因而可以从实际上说,所有的迭代可以转换为递归,但递归不一定可以转换为迭代。51Testing软件测试网 mS[G?
4^gmu)^k:~h0 采用递归算法需要的前提条件是,当且仅当一个存在预期的收敛时,才可采用递归算法,否则,就不能使用递归算法。
~$b*PMwzb0jVJ~ {? _'a0 递归其实是方便了程序员难为了机器,递归可以通过数学公式很方便的转换为程序。其优点就是易理解,容易编程。但递归是用栈机制实现的,每深入一 层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会以内存崩溃而告终,而且递归也带来了大量的函数调用,这也有许多额外的时 间开销。所以在深度大时,它的时空性就不好了。
%N4DB${3Q#FjRl0 51Testing软件测试网%`oYr)rxz而迭代虽然效率高,运行时间只因循环次数增加而增加,没什么额外开销,空间上也没有什么增加,但缺点就是不容易理解,编写复杂问题时困难。51Testing软件测试网|.c;@Qr0G\|1U
51Testing软件测试网7@B6bg'Y;XGlY a因而,“能不用递归就不用递归,递归都可以用迭代来代替”这样的理解,还是辩证的来看待,不可一棍子打死。*/
WDD_G db"UP!Y0 3、个人总结[(po,zH?0
YjHDvH1Rb:uWw0 |
定义51Testing软件测试网N3}3X*M _BRSFU'\ |
优点 y'@([%J.zW0 |
缺点 "~X%S9W(YG]"x0 |
递归 A+a5L~!?2t k&w0 |
程序调用自身的编程技巧称为递归51Testing软件测试网rh3kz7HMU;A!`k!U[ |
1)大问题化为小问题,可以极大的减少代码量; ,n'f"J:M&]r9b@-H){02)用有限的语句来定义对象的无限集合.;51Testing软件测试网)c4V[2e(Y 3)代码更简洁清晰,可读性更好 QS;c-e SS0 |
1)递归调用函数,浪费空间; FgU#z2qva02)递归太深容易造成堆栈的溢出; Z+NFcG.X9\0;{9d.m%l)R2y F*O"e0 |
迭代51Testing软件测试网T!M6Qbl D.h5s N |
利用变量的原值推算出变量的一个新值,迭代就是A不停的调用B.51Testing软件测试网Kd+Ux~)f |
1)迭代效率高,运行时间只因循环次数增加而增加; Y^2i@+E8Uo02)没什么额外开销,空间上也没有什么增加, 8s5j]*C*l0 |
1)不容易理解; hk5f`c'x02)代码不如递归简洁;51Testing软件测试网;\*Cq0~7] f2^@3xj 3)编写复杂问题时困难。51Testing软件测试网-H:R+U aF0M |
二者关系 WYg9O:tp0 |
1)递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换。51Testing软件测试网p;P3A4yS6J 2)能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出./*相对*/51Testing软件测试网 {{ O*l7^D&wJ |
举例如下:
6VH7U/[_m$`0ml-A(?Z!X$o0
51Testing软件测试网o)U#H!Cd6i #include <iostream> //迭代实现斐波那契数列 /yo:ytXF
w0//递归实现斐波那契数列51Testing软件测试网8i9k5Ec9c4M7H-x(i |