一篇帮你搞定C语言“套娃”(递归)

简介: 一篇帮你搞定C语言“套娃”(递归)

前言

前面呢,我们介绍了C语言的函数内容,这次给大家介绍一下C语言的”套娃“(递归)。递归可以把我们日常的大事小事化,那么由我来带大家了解和深入递归。


什么是递归?

程序调用自身的编程技巧称为递归( recursion)。

递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接 调用自身的

一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解, 递归策略

只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

递归的主要思考方式在于:把大事化小

注意前方高能

给大家写一个史上最简单递归代码。

int main()
{
  printf("hehe\n");
  main();
  return 0;
}


运行结果>


9fe9ca6dfb8f4aa09e0787d9d0cef8b9.png


可以看出代码进入了死循环。

我们先来分析一下这个代码>第一次执行打印"hehe"然后接着调用main函数,再打印"hehe",再调用,再打印,就像无限递归一样,就好比镜子里面有个镜子镜子里面有个镜子一直循环下去,但是程序到最后会崩掉(栈溢出了),我们打断点调试一下>



07e22b4072304cb1a8fa5fac50e667e6.png

可以看到他会报出Stack overflow(栈溢出)的异常


2fbf25c0a66c4c069c40ac0a4f53b210.png

由上面内存图我们可以看出在执行mian函数的时候会一直调用main函数,而调用的同时会在栈区上开辟内存空间,照这样递归下去迟早会出现栈溢出,最终程序崩溃,所以说上面的代码是一个错误代码,会发生错误的递归。

那么为了避免以上的情况发生,我们必须要对递归做出限制条件。



递归的两个必要条件

  • 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
  • 每次递归调用之后越来越接近这个限制条件

我们通过几道典型的题目来深入理解一下套娃思路>


练习1

接受一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:1234,输出 1 2 3 4

.我们来试着分析一下>

如何得到每一位数字呢,我们画图看一下


7fb100cdb97c4836a309dd5c3c6d93aa.png


我们用1234%10可以得到他的个位4,再对1234/10可以去掉个位得到123,再对123%10可以得到个位3,然后再对123/10去掉个位得到12,这样依次下去可以得到1234的每一位数字。

我们再来画图看一下



0a7b4cb7441b4d609d37c1eb5dd3b648.png

我们可以把代码拆分成上面这样,当n是一位数的时候不在才分,然后我们看看代码实现>

void print(int n)
{
  if (n > 9)
  {
    print(n / 10);
  }
  printf("%d ", n % 10);
}
int main()
{
  int num = 1234;
  print(num);
  return 0;
}


我们让代码运行试试>


1e39ad7e2b034448a7fae4cabce8ce5a.png

ok没问题是我们要的结果,那代码该怎么理解呢,首先我们要知道递归 的递—“递推”、归—“回归”(递归递归先递再归!)

我们来把代码单独拿出来分析一下>

89ecd66021364b2db25da979355559d7.png

红色的线是,蓝色的线是,看完这个图相信大家已经能够很好的理解递归的过程了。

再来回过头看看这句话:

只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

这就是递归的特点。

那么我们来强调两个重点>




883d237a3bc940dcba7217a5cbb912e8.pngn>9是保证递归能够停下来,n/10是保证递归能够正常按照我们的需求进行下去!



91694f841a1f40e6acc372ae68e43352.png


练习2

求一个数的阶乘(递归实现不考虑溢出)

参考代码:

int factorial(int n)
{
  if (n <= 1)
    return 1;
  else
    return n * factorial(n - 1);
}
int main()
{
  int n = 5;
  int print_factorial = factorial(5);
  printf("%d", print_factorial);
  return 0;
}


我们再画图分析一下代码>


6823de2b9353465baf8cbb0e3ec7ad94.png

还是一样红色的线是递,蓝色的线是归!!!

看了这个图,大家对递归就有了更深一层次的理解!

提示:


1.许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。

2.但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。

3.当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。

总结

以上就是我为大家介绍的C语言“套娃”的基本思想,相信大家看了以上内容一定会对递归有更深层次的理解。

种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!

创作不易,辛苦各位小伙伴们动动小手,三连一波~~~,本文中也有不足之处,欢迎各位随时私信点评指正!

————————————————

版权声明:本文为CSDN博主「cv工程师小智」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/xz2935117143/article/details/128268404

相关文章
|
5月前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
47 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
3月前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
78 7
|
3月前
|
C语言
c语言回顾-函数递归(上)
c语言回顾-函数递归(上)
51 2
|
3月前
|
C语言
c语言回顾-函数递归(下)
c语言回顾-函数递归(下)
50 0
|
5月前
|
机器学习/深度学习 C语言
【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)
要保持最小的步数,每一次汉诺塔问题(无论是最初还是递归过程中的),如果此时初始柱盘子数为偶数,我们第一步是把最上面的盘子移动到中转柱,如果为奇数,我们第一步则是将其移动到目标柱。
112 0
【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)
|
5月前
|
C语言
C语言中的递归
C语言中的递归
|
6月前
|
存储 编译器 C语言
|
5月前
|
算法 编译器 C语言
【C语言】递归
【C语言】递归
27 0
|
7月前
|
机器学习/深度学习 算法 C语言
详细介绍递归算法在 C 语言中的应用,包括递归的基本概念、特点、实现方法以及实际应用案例
【6月更文挑战第15天】递归算法在C语言中是强大力量的体现,通过函数调用自身解决复杂问题。递归涉及基本概念如自调用、终止条件及栈空间管理。在C中实现递归需定义递归函数,分解问题并设定停止条件。阶乘和斐波那契数列是经典应用示例,展示了递归的优雅与效率。然而,递归可能导致栈溢出,需注意优化。学习递归深化了对“分而治之”策略的理解。**
136 7
|
7月前
|
C语言
C语言--函数递归与迭代
C语言--函数递归与迭代