递归与非递归的转换

Posted 4nc414g0n

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归与非递归的转换相关的知识,希望对你有一定的参考价值。

递归

用递归解决的三类问题

  1. 数据的定义是按递归定义的。(Fibonacci函数,n的阶乘)
  2. 问题解法按递归实现。(回溯)
  3. 数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索)

递归相对于循环迭代的问题:

  1. 递归太深,导致栈溢出线性递归
  2. 性能问题(现在编译器优化越来愈好,此问题在相对变得不那么重要)

以斐波那契数列为例

线性递归
long long Fib(size_t N)
{
	if(N < 3)
		return 1;
	return Fib(N-1) + Fib(N-2);
}


每次调用时是先调用Fib(n-1),再调用Fib(n-2),所以图中第一列是最先被调用的,由于空间不累计性,空间复杂度按最多的第一列算O(N)


在调用递归调用Fib(n-1)的时候,Fib(n-2)还没有执行,需要保存前面的状态,因此开销较大

尾递归
int Fib(int n, int ret1, int ret2)
{
   if (n == 0)
       return ret1;
   else 
       return Fib(n-1, ret2, ret1 + ret2);
}
  1. 尾递归的判断标准是函数运行最后一步是否调用自身,而不是是否在函数的最后一行调用自身
  2. 一般尾递归在写法上主要会把上次运行的结果通过参数进行传递
  3. 空间复杂度O(1)

尾调用的重要性在于它可以不在调用栈上面添加一个新的堆栈帧——而是更新它,如同迭代一般。尾递归因而具有两个特征: 调用自身函数(Self-called); 计算仅占用常量栈空间(Stack Space)。 而形式上只要是最后一个return语句返回的是一个完整函数,它就是尾递归。

递归转换为非递归

循环迭代

尾递归
例子数据结构----排序 中的归并排序非递归解法

栈或队列+循环迭代

线性递归
例子数据结构----排序 中的快速排序非递归解法

以上是关于递归与非递归的转换的主要内容,如果未能解决你的问题,请参考以下文章

递归算法之阶乘代码实现与非递归实现

C++实现二叉树 前中后序遍历(递归与非递归)非递归实现过程最简洁版本

基于Java的二叉树的三种遍历方式的递归与非递归实现

每天刷个算法题20160521:二叉树高度(递归与非递归)

java扫描文件夹下面的所有文件(递归与非递归实现)

二分查找算法(递归与非递归两种方式)