递归与非递归的转换

递归

用递归解决的三类问题

  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语句返回的是一个完整函数,它就是尾递归。

递归转换为非递归

循环迭代

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

栈或队列+循环迭代

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值