深究递归和迭代的区别、联系、优缺点及实例对比

简介: 递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己.一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合.

深究递归和迭代的区别、联系、优缺点及实例对比

1.概念区分


递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己.


一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合.


使用递归要注意的有两点:


1)递归就是在过程或函数里面调用自身;


2)在使用递归时,必须有一个明确的递归结束条件,称为递归出口.


递归分为两个阶段:


1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解;


2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解.


利用递归可以解决很多问题:如背包问题,汉诺塔问题,...等.


斐波那契数列为:0,1,1,2,3,5...


由于递归引起一系列的函数调用,并且有可能会有一系列的重复计算,递归算法的执行效率相对较低.


迭代:利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B.


2.辩证看递归和迭代


所谓递归,简而言之就是应用程序自身调用自身,以实现层次数据结构的查询和访问。递归的使用可以使代码更简洁清晰,可读性更好(对于初学者到不见得),但由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。


往往有这样的观点:能不用递归就不用递归,递归都可以用迭代来代替。


诚然,在理论上,递归和迭代在时间复杂度方面是等价的(在不考虑函数调用开销和函数调用产生的堆栈开销),但实际上递归确实效率比迭代低,既然这样,递归没有任何优势,那么是不是就,没有使用递归的必要了,那递归的存在有何意义呢?


万物的存在是需要时间的检验的,递归没有被历史所埋没,即有存在的理由。从理论上说,所有的递归函数都可以转换为迭代函数,反之亦然,然而代价通常都是比较高的。但从算法结构来说,递归声明的结构并不总能够转换为迭代结构,原因在于结构的引申本身属于递归的概念,用迭代的方法在设计初期根本无法实现,这就像动多态的东西并不总是可以用静多态的方法实现一样。这也是为什么在结构设计时,通常采用递归的方式而不是采用迭代的方式的原因,一个极典型的例子类似于链表,使用递归定义及其简单,但对于内存定义(数组方式)其定义及调用处理说明就变得很晦涩,尤其是在遇到环链、图、网格等问题时,使用迭代方式从描述到实现上都变得不现实。因而可以从实际上说,所有的迭代可以转换为递归,但递归不一定可以转换为迭代。


采用递归算法需要的前提条件是,当且仅当一个存在预期的收敛时,才可采用递归算法,否则,就不能使用递归算法。


递归其实是方便了程序员难为了机器,递归可以通过数学公式很方便的转换为程序。其优点就是易理解,容易编程。但递归是用栈机制实现的,每深入一层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会以内存崩溃而告终,而且递归也带来了大量的函数调用,这也有许多额外的时间开销。所以在深度大时,它的时空性就不好了。


而迭代虽然效率高,运行时间只因循环次数增加而增加,没什么额外开销,空间上也没有什么增加,但缺点就是不容易理解,编写复杂问题时困难。


因而,“能不用递归就不用递归,递归都可以用迭代来代替”这样的理解,还是辩证的来看待,不可一棍子打死。*/


1,2部分摘自网络,略有改动,向原作者致敬!


3.个人总结



定义


优点


缺点


递归


程序调用自身的编程技巧称为递归


1)大问题化为小问题,可以极大的减少代码量;


2)用有限的语句来定义对象的无限集合.;


3)代码更简洁清晰,可读性更好


1)递归调用函数,浪费空间;


2)递归太深容易造成堆栈的溢出;



迭代


利用变量的原值推算出变量的一个新值,迭代就是A不停的调用B.


1)迭代效率高,运行时间只因循环次数增加而增加;


2)没什么额外开销,空间上也没有什么增加,


1) 不容易理解;


2) 代码不如递归简洁;


3) 编写复杂问题时困难。


二者关系


1) 递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换。


2) 能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出./*相对*/


举例如下:


#include <iostream>

using namespace std;

//迭代实现斐波那契数列

long fab_iteration(int index)

{

if(index == 1 || index == 2)

{

 return 1;

}

else

{

 long f1 = 1L;

 long f2 = 1L;

 long f3 = 0;

 for(int i = 0; i < index-2; i++)

 {  

  f3 = f1 + f2; //利用变量的原值推算出变量的一个新值

  f1 = f2;

  f2 = f3;

 }

  return f3;

}

}

//递归实现斐波那契数列

long fab_recursion(int index)

{    

if(index == 1 || index == 2)

{

 return 1;

}

else

{

 return fab_recursion(index-1)+fab_recursion(index-2);    //递归求值

}

}

int main(int argc, char* argv[])

{

cout << fab_recursion(10) << endl;

cout << fab_iteration(10) << endl;

return 0;

}


相关文章
|
7月前
|
存储 搜索推荐 算法
Java数组全套深入探究——进阶知识阶段2、冒泡排序
Java数组全套深入探究——进阶知识阶段2、冒泡排序
89 0
|
1月前
|
存储 开发者
递归比较的优缺点是什么?
【10月更文挑战第29天】递归比较是一种在处理复杂数据结构时常用的比较方法,尤其适用于对象和数组等引用类型数据的深度比较。
|
1月前
|
算法
尾递归和迭代的区别是什么?
【10月更文挑战第24天】尾递归和迭代各有优缺点,在实际编程中需要根据具体情况选择合适的方法。在一些情况下,尾递归可以提供更简洁高效的实现方式;而在另一些情况下,迭代可能是更为可靠的选择。
|
1月前
|
算法 程序员 编译器
尾递归和迭代的优缺点
【10月更文挑战第24天】在实际编程中,选择尾递归还是迭代往往取决于具体的问题和需求。有时候可以结合两者的优点,根据情况灵活运用。
|
6月前
|
机器学习/深度学习 算法 C语言
详细介绍递归算法在 C 语言中的应用,包括递归的基本概念、特点、实现方法以及实际应用案例
【6月更文挑战第15天】递归算法在C语言中是强大力量的体现,通过函数调用自身解决复杂问题。递归涉及基本概念如自调用、终止条件及栈空间管理。在C中实现递归需定义递归函数,分解问题并设定停止条件。阶乘和斐波那契数列是经典应用示例,展示了递归的优雅与效率。然而,递归可能导致栈溢出,需注意优化。学习递归深化了对“分而治之”策略的理解。**
132 7
|
7月前
|
搜索推荐
搜索树基础:二叉搜索树(详解特性用途,图解实现过程)
搜索树基础:二叉搜索树(详解特性用途,图解实现过程)
|
7月前
|
搜索推荐 Java 程序员
Java数组全套深入探究——进阶知识阶段1、选择排序
Java数组全套深入探究——进阶知识阶段1、选择排序
55 0
|
7月前
|
算法 Java 程序员
Java数组全套深入探究——基础知识阶段4、数组的遍历
Java数组全套深入探究——基础知识阶段4、数组的遍历
74 0
|
缓存 算法 Java
使用迭代优化递归程序
大家好,我是王有志。 今天我们将会分析上篇文章中递归算法存在的问题,并通过迭代去优化。
118 1
使用迭代优化递归程序