转 自 : https://blog.csdn.net/fbz123456/article/details/50959412

递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解。对于某些复杂问题(例如hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,但是递归算法的执行效率通常比较差。因此,在求解某些问题时,常采用递归算法来分析问题,用非递归算法来求解问题;另外,有些程序设计语言不支持递归,这就需要把递归算法转换为非递归算法。
    将递归算法转换为非递归算法有两种方法,一种是直接求值(迭代/循环),不需要回溯;另一种是不能直接求值,需要回溯。前者使用一些变量保存中间结果,称为直接转换法;后者使用栈保存中间结果,称为间接转换法,下面分别讨论这两种方法。

1. 直接转换法
直接转换法通常用来消除尾递归和单向递归,将递归结构用循环结构来替代。
单向递归:简单的说是指递归的过程总是朝着一个方向进行,如果函数1调用了函数2,而函数2又调用了函数1,则这种情况不属于单向递归。斐波那契数列的递归求解可转用一个迭代法实现。

斐波那契数列的递归求解:

int Fib(int n) {
if(n <= 1) return n;
else return Fib(n - 1) + Fib(n - 2);
}

转化为迭代求解:

int Fib(int n) {
if(n <= 1) return n;
int twoBack = 0;
int oneBack = 1;
int cur;
for(int i = 2;i < = n; i++) {
   cur = twoBack + oneBack;
twoBack = oneBack;
   oneBack = cur;
}
return cur;
}

尾递归函数是以递归调用结尾的函数,是单向递归的特例。它的递归调用语句只有一个,而且是放在过程的最后。当递归调用返回时,返回到上一层递归调用语句的下一语句,而这个位置正好是程序的结尾,因此递归工作栈中可以不保存返回地址;除了返回值和引用值外,其他参数和局部变量都不再需要,因此可以不用栈,直接采用循环写出非递归过程。

阶乘函数就不是一个尾递归。因为在它收到递归调用的结果后,必须在返回调用前再做一次乘法运算。但是阶乘函数可以转化成一个尾递归函数,例:

阶乘的递归求解:

int factorial(int n)

{
if(n == 0) return 1;
else

{
int val = factorial(n - 1);
return n * val;
}
}

转化为尾递归求解:

int factorial(int acc, int x)

{ //acc传的值为1。
if(x <= 1) return acc;
else

return factorial(x * acc, x - 1);
}

尾递归的重要性在于当进行尾递归调用时,调用者的返回位置不需要被存在调用栈里。当递归调用返回时,它直接分支到先前已保存的返回地址。因此,在支持尾递归优化的编译器上,尾递归在时间和空间上都比较划算。迭代算法需要一个临时变量,这无疑导致了程序的可读性降低,迭代函数不像递归函数那样需要考虑函数调用的支出,而且对一个线程来说可用的栈空间通常比可用的堆空间要少得多,而递归算法则相对迭代算法需要更多的栈空间!

2. 间接转换法
该方法使用栈保存中间结果,一般需根据递归函数在执行过程中栈的变化得到。其一般过程如下:

将初始状态s0进栈
while (栈不为空)
{
退栈,将栈顶元素赋给s;
if (s是要找的结果) 返回;
else {
寻找到s的相关状态s1;
将s1进栈
}
}

间接转换法在数据结构中有较多实例,如二叉树遍历算法的非递归实现、图的深度优先遍历算法的非递归实现等等,请读者参考主教材中相关内容。

递归算法转换为非递归算法相关推荐

  1. 递归算法转换为非递归算法的技巧

    递归算法转换为非递归算法的技巧 递归函数具有很好的可读性和可维护性,但是大部分情况下程序效率不如非递归函数,所以在程序设计中一般喜欢先用递归解决问题,在保证方法正确的前提下再转换为非递归函数以提高效率 ...

  2. zz 递归算法转换为非递归算法

    from:http://blog.csdn.net/Shunrei/archive/2010/06/19/5680579.aspx 递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解 ...

  3. 递归算法到非递归算法的转换

    递归实质在定义自身的同时又出现了对自身的调用.递归算法是许多软件编程人员常用的方法,结构简单.清晰.可读性好.但在实际应用中也存在一些问题:1.并不是每一门语言都支持递归,比较典型的FORTRAN语言 ...

  4. 递归算法向非递归算法转换

    递归算法向非递归算法转换 递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解.对于某些复杂问题(例如hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,但是递归算法的执 ...

  5. 递归算法与非递归算法的转化

    递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解.对于某  些复杂问题(例如 hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,  但是递归算法的执行效率通常比较差 ...

  6. 递归算法与非递归算法比较

    转载自:https://blog.csdn.net/mhsszm/article/details/78445591 非递归效率高:递归代码写出来思路清晰,可读性强. 生成可执行文件大小应该和编译器有关 ...

  7. 遍历二叉树的递归算法与非递归算法

    遍历二叉树的递归算法与非递归算法 先来看下面这棵二叉树.如图1.现在我们要对它进行先序遍历.递归思想:就是把这个大树拆分成N棵小树,每棵小树都进行一次先序遍历.再把这些遍历连合起来就是这棵树的先序遍历 ...

  8. Hanoi塔问题的递归算法与非递归算法

    1. 递归算法: n=1时,很简单只需要将编号为1的圆盘从A移动到B即可. n>1时,只需要利用辅助塔C,先将n-1个较小的圆盘移动到C塔,再将剩下最大的圆盘移动到B塔,最后再将n-1个圆盘从C ...

  9. 斐波那契数列递归算法和非递归算法以及其时间复杂度分析

    1.在学习数据结构这门课的过程中,发现斐波那契数列的递归算法以及非递归算法,以及其时间复杂度分析是一个小难点.所以特别总结一下. 斐波那契数列的表达式: Fibonacci数列简介: F(1)=1 F ...

最新文章

  1. 网页中如何显示版权符号
  2. 我怎么在AD里面找到已经改名的Administrator账户?
  3. InitializeComponent()有什么作用?
  4. antd option宽度自适应_Web移动端实现自适应缩放界面的方法汇总
  5. pageadmin CMS网站建设教程:站点添加自定义字段
  6. JAVA核心:内存、比较和Final
  7. 实验3.2 定义一个简单的Computer类
  8. SSM 生成mapper中xml文件:未能解析映射资源:“文件嵌套异常
  9. MySQL字符集设置及字符转换(latin1转utf8)
  10. Vue开发实例(02)之将Vue项目代码导入到IDEA并运行
  11. 手机桌面隐藏大师_【应用隐藏大师app】应用隐藏大师安卓版_应用隐藏大师手机版下载v2.8.1 - 绿点安卓网...
  12. 最近抖音超火的60帧高清视频制作教程
  13. Windows10键盘快捷键大全
  14. Uncaught TypeError: $(...).modal is not a function
  15. 全国多省市遭暴雪袭击!这些路段交通受阻!
  16. CloudComparePCL 点云OOB包围盒
  17. 人工智能导论实验二 食人族传教士过河+黑白棋 prolog+Python
  18. nvme固态硬盘开机慢_6个固态硬盘优化设置技巧 让你的SSD速度飞起来 (全文)
  19. [案例4-4]学生和老师
  20. android+读书笔记

热门文章

  1. 吴恩达深度学习相关资源下载地址(蓝奏云)
  2. 详细说明register关键字
  3. Hexo个人博客绑定域名
  4. linux http连接超时时间设置,Linux 下 HTTP连接超时
  5. 百度地图 -- 离线地图开发
  6. 苹果笔记本win7系统触摸板无法右键功能
  7. IIS或Apache部署Django项目时,Admin后台管理CSS样式丢失?
  8. 电路的基本概念(1) 自学笔记
  9. 说极路由牛逼的人们,你们用过Tomato DualWAN吗?(三)
  10. 山东python编程培训,Python进入山东省小学教材了