C语言【递归与迭代】-- 附案例

对于像我一样接触函数不久的小小程序员来说“递归”简直是梦魇,这篇文章我就来讲讲我对它的看法,希望能解决它!

1. 递归是什么?

函数直接或间接调用自身的方法称为递归( recursion)。

递归的主要原理是将转化、分解。把一个复杂且有规律的问题层层转化为一个与原问题相似的规模较小的问题来求解, 并且它只需少量的代码就可以进行解题过程所需要的多次重复计算,极大地减少了程序的代码量。

2. 递归不崩溃所必需的条件!

2.1 必须有结束条件

刚才说到递归就是自己调用自己,但是也不能一直调用吧,因此就需要一个有限制性的条件来结束它,来避免栈溢出导致程序崩溃。

2.2 必须越来越接近结束条件

第二个重要的是每调用自己一次就越要靠近结束条件,直到满足结束条件,如果离它越来越远,递归就不会停止,仍然会栈溢出。

附:栈溢出
系统分配给程序的栈空间是有限的,但是如果出现了死循环(死递归),这样有可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,第二就是当递归的深度或广度太大也会栈空间耗尽-,这样的现象我们称为栈溢出。

3.递归例题

3.1 接受一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入:1234,输出 1 2 3 4.
我们知道 1234 % 10 能得到个位数 4 ,1234 / 10 能得到123,要是这样打印只能输出4 3 2 1 ,而想输出1 2 3 4就可以借用数组,但是如果用递归的方法就很简便。
现在我们得到4和123,不妨这样想,先打印123中的1 2 3 再去打印 4,当打印123时,又可以拿到3和12 ,此时可以先打印12,再打印3,同理打印12就先打印1,在打印 2,打印完12就可以打印3,打印4,结果1 2 3 4便打印出来了。

从而写出这样递归函数:

void print(unsigned int n)
{
	if (n > 9)//结束条件
	{
		print(n / 10);//左移(向结束条件靠拢)
	}
	printf("%d ", n % 10);//打印个位
}

全部的递归路径:
在这里插入图片描述

3.2 求第n个斐波那契数

可能有些人不了解 “斐波那契数列”(Fibonacci),指的是这样一个数列:
1、1、2、3、5、8、13、21、34、……,简单来说是后一个数等于前两个数之和(N > 2)。

现在给一个数,让你通过递归得到这个位置的值。(不考虑栈溢出)

其实这个题目非常简单,我们一定要想着去把大事化小,如果给的 5 ,要得到这个位置的值就要先得到 它的前一位和前两位的值,同理想得到前一位的值就先得到它的前一位和前两位,直到得到数列开头的 1 1 ,就得到第三位 2 ,也就得到第四位 3 ,最后就得到 5

int fibonacci(int n)
{
	if (n <= 2)//第一位和第二位都是1
	{
		return 1;
	}
	return fibonacci(n-1) + fibonacci(n - 2);//前两个相加
}

全部得递归路径:
在这里插入图片描述

4. 迭代代替非递归如何解决问题?

迭代是重复执行一系列运算步骤,从前面的量依次求出后面的量的过程。

按当前所学知识来理解就是循环。每一次迭代得到的值作为下一次迭代的初始值,并且会向结果值靠拢,与递归有着相似之处。
有时候它能和递归解决同样的问题,但是代码量会比递归多上很多且可读性差,但是有一点,它不会溢出,系统只给有限的空间,当递归深度足够大时就会溢出,例如上述的求 Fibonacci数列中的值。

在这里插入图片描述
如果你的参数比较大,那就会报错: stack overflow(栈溢出)这样的信息。

为什么求Fibonacci的值,当参数大一些时会栈溢出呢?
再看上面的递归路径时,4计算一次,3计算二次,2计算三次,1计算二次,此时会发现大量的重复计算,这还只是5而已,如果数字大一些就会运行很久,再大一些就溢出了,大概50之后的就很难计算出来了,最终栈空间就这样被耗尽了。

那么如何解决这个问题呢?
迭代就是比较常用的方法!

设置三个变量a、b、c,首先赋值为1,由于我们将a,b作为第一二个数,c是存a,b的和,作为它们的下一个数,当n是1或2时将不用计算,答案就是1,因此c赋1,当n大于2 时,进入循环,此时c就等于前两个数之和,就求出了第三个数,又将第二个数(b)给a,第三个数©给b,以此循环,求出第n个数。
在这里插入图片描述

正常情况下我们优先考虑递归,因为它实在是方便简洁,如果递归有着明显的效率或溢出问题的时候才用非递归解决!

求三连支持,谢谢!

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值