首页 > 代码库 > 迭代与递归
迭代与递归
前些天,在看Moden C++ 时,突然想到迭代与递归是不是同一个东本,在我的脑子时原本是认为两者是一样,但在好奇的情况下baidu了下,发现两者是不一样的,刚好我有一个程序用的是递归,想着,有没有办法优化。所以就了解下。
以下是网上找的一些信息
递归函数在运行时将带来一部分运行时开销:参数必须压栈、为局部变量分配内存、寄存器的值必须保存等;当递归函数每次调用返回时,上述的操作都需要还原恢复成原来的样子。因此递归函数的效率并不会很高;
一个递归的函数往往可以改写成迭代的形式,而迭代比递归的效率要高很多,许多问题以递归的方式进行描述并不是因为这种问题适合使用递归的方式来解决,而 是因为使用递归描述更简洁直观,这些问题的迭代实现往往比递归要好的多,虽然代码的可读性要差一点儿,但是当一个问题相当复杂时,递归的简洁性可以弥补它 的运行时开销。
这里有一个比较极端的例子,斐波那契数列,它常常以递归的形式进行描述:当n <= 1 时,Fibonacci(n) = 1;当 n = 2 时,Fibonacci(n) = 1;当n > 2 时,Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2);
这种描述方式很容易诱导人们使用递归函数来解决问题:
long Fibonacci( int n )
{
if( n <= 2 )
{
return 1;
}
return ( Fibonacci(n-1) + Fibonacci(n-2) );
}
分析一下最后一跳语句,在计算Fibonacci(n-1)时,将计算一次Fibonacci(n-2),但是在后面又有一次计算 Fibonacci(n-2)的值的情况,这将会造成一次冗余计算,然而实际情况却比这个要糟糕的多,每一个递归调用到会触发另外两个递归调用,而这两个 递归调用中的任何一个又都会触发两个递归调用,这样冗余计算的数量将增长的非常快。例如在执行Fibonacci(10)时,Fibonacci(3)将 会被执行21次,但是递归计算Fibonacci(30)时,Fibonacci(3)将会被计算30多万次(可以使用一个静态变量来计算 Fibonacci(3) 的执行次数)!!当这30多万次的计算结果都是一样的,处了其中一个是必须的其他的都属于浪费。
现在如果使用迭代来解决这个问题,程序的效率提高将是巨大的,尤其是n的值相当大的时候:
long Fibonacci( int n )
{
long result;
long previous_result;
long next_older_result;
result = previous_result = 1;
while ( n > 2 )
{
n -= 1;
next_older_result = previous_result;
previous_result = result;
result = next_older_result + previous_result;
}
return result;
}
总结:递归写法简单易懂,代码流程清晰,但是每次都是调用函数自身需要占用许用资源,如果是递归次数大,因为需要堆栈,容易造成栈溢出。
而迭代是在栈内多次循环,所以不存在这个问题,对比两个,考虑到效率的应该用迭代,网上说递归都可以转为迭代,有的也说只有能尾递归的(从最后一个表达式
往回推导)才能转为迭代,据本人测验,迭代中借助变量,似乎可以完成递归转迭代,但却需要更多的脑力去控制。所以有人说,递归为难机器,迭代为难人
相比递归,迭代逻辑控制复杂,需要借助额外变量存储中间量,另外代码他人不易懂。所以用迭代还是递归,需要自己掌握。