爱上C语言:函数递归,青蛙跳台阶图文详解

简介: 爱上C语言:函数递归,青蛙跳台阶图文详解

🚀前言

大家好啊😉!今天阿辉将为大家介绍C语言中的函数的递归,✍包括什么是函数递归,函数递归的必要条件,青蛙跳台阶问题(斐波那契数列)以及栈溢出问题,内容干货满满😋,接下来就跟着阿辉一起学习吧👊

🚀什么是函数递归?

函数递归:简单来说就是函数自己调自己。

递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明
中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与
原问题相似的规模较小的问题来求解
   递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了
程序、的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递
归需要、有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当
边界条件满足时,递归返回。

🚀函数递归的必要条件

  • 递归存在限制条件,当满足限制条件时函数便不再不在递归下去了
  • 每一次递归后都会逐渐接近这个限制条件

这两个条件是必要的,否则将陷入死递归

我们来看个例子👇

#include<stdio.h>
int main()
{
  printf("hallo c !\n");
  main();
  return 0;
}

上面这段代码你在VS上调试的话就会报错

栈溢出是什么?别急后面会讲,我们接着看👊

🚀 用递归求n的阶乘

5! = 5*4*3*2*1  4! = 4*3*2*1
3! = 3*2*1      2! = 2*1
1! = 1      0! = 1
我们看出求 5!可以变成求 5*4!
而4! = 4*3!  3! = 3*2! 2! = 2*1!

以此类推由上图我们把青蛙跳台阶抽象成下面这个模型👇

把n的阶乘记作Fac(n)

由上图我们可以写出n的阶乘的函数递归代码

int Fac(int n)
{
  if (n < 2)
    return 1;
  else
    return n * Fac(n - 1);
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  int a = Fac(n);
  printf("%d\n", a);
  return 0;
}

🚀青蛙跳台阶问题(斐波那契数列

一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法

上图我们可知,青蛙跳n次台阶的跳法可以分成:青蛙跳(n - 1)次台阶的跳法加上青蛙跳(n - 2)次台阶的跳法

而青蛙跳(n - 1)次台阶的跳法又可以分成:青蛙跳(n - 2)次台阶的跳法加上青蛙跳(n - 3)次台阶的跳法

以此类推由上图我们把青蛙跳台阶抽象成下面这个模型👇

把青蛙跳n次台阶的次数记作Fib(n)

上图其实也就是斐波那契数列得到的方法,只不过斐波那契数列前两个数都是1

由上图我们可以写出青蛙跳台阶的函数递归代码

#include<stdio.h>
int Fib(int n)
{
  if (n < 3)
    return n;
  else
    return Fib(n - 1) + Fib(n - 2);
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  int a = Fib(n);
  printf("%d\n", a);
  return 0;
}

虽然递归能以很少的代码量解决复杂的问题,但是如果递归程度太深,递归次数太多将导致效率低下,甚至栈溢出

上述n的阶乘以及青蛙跳台阶都可以用迭代的方式去写,效率更高,利用的栈内存更小

迭代版本n的阶乘以及青蛙跳台阶奉上👊

n的阶乘

int Fac(int n)
{
  int i = 0;
  int ret = 1;
  for (i = 1; i <= n; i++)
  {
    ret *= i;
  }
  return ret;
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  int a = Fac(n);
  printf("%d\n", a);
  return 0;
}

青蛙跳台阶:

int Fib(int n)
{
  int a = 1;
  int b = 2;
  int c = 0;
  if (n < 3)
    return n;
  while (n - 2)
  {
    c = a + b;
    a = b;
    b = c;
    n--;
  }
  return c;
}
int main()
{
  int n = 0; 
  scanf("%d", &n);
  int a = Fib(n);
  printf("%d\n", a);
  return 0;
}

🚀什么是栈溢出?

,又称堆栈,是一种具有一定规则的数据结构,它按照先进后出的原则存储数据,先存的元素放在栈底,后存的元素在栈顶。

栈区存放函数参数以及局部变量等。内存由编译器分配和释放。

那么栈溢出又是什么呢?

栈溢出是指向向栈中写入了超出限定长度的数据,溢出的数据会覆盖栈中其它数据,从而影响程序的运行

而递归每调一次函数都会向栈区申请一块内存空间,如果死递归或者递归层次太深都会导致栈溢出。

SO递归虽好,可不要贪杯啊


到这里,阿辉今天对于C语言函数递归的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹

相关文章
|
11天前
|
C语言
C语言:内存函数(memcpy memmove memset memcmp使用)
C语言:内存函数(memcpy memmove memset memcmp使用)
|
5天前
|
缓存 安全 编译器
【C 言专栏】C 语言函数的高效编程技巧
【5月更文挑战第1天】本文探讨了C语言中函数的高效编程技巧,包括函数的定义与作用(如代码复用和提高可读性)、设计原则(单一职责和接口简洁)、参数传递方式(值传递、指针传递和引用传递)、返回值管理、调用约定、嵌套与递归调用,以及函数优化技巧和常见错误避免。掌握这些技巧能提升C语言代码的质量和效率。
【C 言专栏】C 语言函数的高效编程技巧
|
7天前
|
C语言
pta浙大版《C语言程序设计(第3版)》 习题6-4 使用函数输出指定范围内的Fibonacci数 (20分)
pta浙大版《C语言程序设计(第3版)》 习题6-4 使用函数输出指定范围内的Fibonacci数 (20分)
|
7天前
|
C语言
pta 浙大版《C语言程序设计(第3版)》题目集 习题6-6 使用函数输出一个整数的逆序数 (20分)
pta 浙大版《C语言程序设计(第3版)》题目集 习题6-6 使用函数输出一个整数的逆序数 (20分)
|
7天前
|
C语言
(浙大版《C语言程序设计(第3版)》 习题6-5 使用函数验证哥德巴赫猜想 (20分)
(浙大版《C语言程序设计(第3版)》 习题6-5 使用函数验证哥德巴赫猜想 (20分)
|
9天前
|
安全 C语言
【C语言】strcpy与strncpy函数的使用和模拟实现
【C语言】strcpy与strncpy函数的使用和模拟实现
5 0
|
9天前
|
C语言
【C语言】字符分类函数与字符转换函数
【C语言】字符分类函数与字符转换函数
9 1
|
9天前
|
程序员 编译器 C语言
C语言之函数与参数
C语言之函数与参数
7 0
|
11天前
|
C语言
C语言:字符函数和字符串函数(strlen strcat strcmp strncmp等函数和模拟实现)
C语言:字符函数和字符串函数(strlen strcat strcmp strncmp等函数和模拟实现)
|
11天前
|
机器学习/深度学习 C语言
函数递归深入解析(C语言)
函数递归深入解析(C语言)