利用迭代算法处理问题,需要做好以下三个方面的工做:
一、确定迭代变量。在能够用迭代算法处理的问题中,至少具有一个间接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。
二、建立迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。迭代关系式的建立是处理迭代问题的关键,通常能够使用递推或倒推的方法来完成。
三、对迭代过程进行控制。在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,能够计算出来;另一种是所需的迭代次数无法确定。对于前一种情况,能够建立一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的条件。
程序调用本身的编程技巧称为递归( recursion)。 在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口。
能采用递归描述的算法通常有这样的特征:为求解规模为N的问题,设法将它分解成规模较小的问题,然后从这些小问题的解方便地构造出大问题的解,并且这些规模较小的问题也能采用同样的分解和综合方法,分解成规模更小的问题,并从这些更小问题的解构造出规模较大问题的解。特别地,当规模N=1时,能直接得解。递归算法的执行过程分递推和回归两个阶段。在递推阶段,把较复杂的问题(规模为n)的求解推到比原问题简单一些的问题(规模小于n)的求解。在递推阶段,必须要有终止递归的情况。在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解。
采用递归算法需要的前提条件是,当且仅当一个存在预期的收敛时,才可采用递归算法,否则,就不能使用递归算法。 迭代虽然效率高,运行时间只因循环次数增加而增加,没什么额外开销,空间上也没有什么增加,但缺点就是不容易理解,编写复杂问题时困难。
经常的看到“递归算法”、“非递归算法”,这种提法没有语义上的问题,并且我自己也这样用——递归的算法。但这也正说明了,递归不是算法,他是一种思想,正是因为某个算法的指导思想是递归的,所以才被称为递归算法;而一个有递归算法的问题,当你不使用递归作为指导思想,这样得到的算法就是非递归算法。——而对于循环能处理的问题,都有递归解法,在这个意义上说,循环算法都可以称为非递归算法。
一些经典的递归问题:
[P1] 一个饲养场引进一只刚出生的新品种兔子,这种兔子从出生的下一个月开始,每月新生一只兔子,新生的兔子也如此繁殖。如果所有的兔子都不死去,问到第 12 个月时,该饲养场共有兔子多少只?
[P2] 阿米巴用简单分裂的方式繁殖,它每分裂一次要用 3 分钟。将若干个阿米巴放在一个盛满营养参液的容器内, 45 分钟后容器内充满了阿米巴。已知容器最多可以装阿米巴 2 20 个。试问,开始的时候往容器内放了多少个阿米巴?
[P3] 日本数学家谷角静夫在研究自然数时发现了一个奇怪现象:对于任意一个自然数 n ,若 n 为偶数,则将其除以 2 ;若 n 为奇数,则将其乘以 3 ,然后再加 1 。如此经过有限次运算后,总可以得到自然数 1 。人们把谷角静夫的这一发现叫做“谷角猜想”。
迭代(iterative)和递归(recursive)可以相互转化。常常要求把递归转化为迭代。因为递归得耗费大量时间。递归的使用可以使代码更简洁清晰,可读性更好(对于初学者到不见得),但由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。在理论上,递归和迭代在时间复杂度方面是等价的(在不考虑函数调用开销和函数调用产生的堆栈开销),但实际上递归确实效率比迭代低。从算法结构来说,递归声明的结构并不总能够转换为迭代结构。从实际上说,所有的迭代可以转换为递归,但递归不一定可以转换为迭代。比如著名的Ackmann函数。任何的一种语言里面都有循环结构,但不是任何的语言都支持递归。
非递归化就是指不引入堆栈等辅助空间进行计算的算法。更确切地说,非递归是指辅助的空间为O(1)的算法(辅助空间的规模和问题的输入规模无关)。引入堆栈的所谓非递归本质上还是递归,只不过原来由编译器做的事让你的程序来模拟实现了。不是所有的可计算问题都可以由递归转化为递推的。例如著名的Ackermann函数,就没有递推算法,除非引入堆栈等辅助结构。
递归转迭代的方法:
尾递归:普通的线性递归比尾递归更加消耗资源。尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量. 直接让被调用的函数返回时越过调用者, 返回到调用者的调用者去.
一个尾递归函数很容易转化为迭代。
然而通常所见到的递归都不是尾递归形式,这时候我们可以想办法用等价变换将其变化为等价的尾递归形式。尾递归是最简单的一类直接可以转化为递推的递归算法,另外还有很多方法将递归转化为递推,例如利用Cooper变换,反演变换,T1,T2变换,C变换,RR变换等。
http://blog.csdn.net/politefish/article/details/4504798 迭代算法与递归算法的概念及区别
http://blog.sina.com.cn/s/blog_4d3f5a400100h9y0.html
http://www.4ucode.com/Study/Topic/1910521 关于尾递归
http://www.cnblogs.com/fengjun/archive/2011/11/09.html