函数递归-------套娃套路深,要么你玩递归,要么递归玩你

简介: 函数递归-------套娃套路深,要么你玩递归,要么递归玩你

什么是递归?

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

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

调用自身的

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

递归策略

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

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

简单的来讲就是不断的套用自身的函数来达到能多次跟循环一样的效果,且代码简单

递归的两个必要条件

(1)存在限制条件,当满足这个限制条件的时候,递归便不再继续。

(2)每次递归调用之后越来越接近这个限制条件

简单说就是需要判断,调用自身的时候传入的参数不能和原函数相同,

可能有些小可爱们还是不怎么理解,那我们来操作一下:

练习1;

接受一个整型值(无符号),按照顺序打印它的每一位

如输入1234,就打印出1234

思路:

当只有个位数直接打印即可,当超过1位数,我们用%10来得出余数,打印余数

代码如下:

void My_print(unsigned int inp)//正向打印
{
    if(inp/10)
    {
        My_print(inp/10);
    }
    printf("%d",inp%10);
}
void My_print_(unsigned int inp)//反向打印
{
    printf("%d",inp%10);
    if(inp/10)
        My_print_(inp/10);
}
int main()
{
    unsigned int inp=0;
    printf("请输入数字:>");
    scanf("%d",&inp);
    My_print(inp);
    return 0;
}

运行结果:

递归第一步是要先判断条件,写明判断条件就可以避免死循环

可能一题还不足以学会,我们接着来:

练习2:

编写函数不允许创建临时变量,求字符串的长度

思路:

在c语言中有strlen()计算字符串个数不计算'\0',我采用的是这个思路,

代码如下:

#include <stdio.h>
int num_strlen(char* arr)
{
    if(*arr!='\0')
    {
        return (1+num_strlen(arr+1));
    }
    return 0;
}
int main()
{
    char arr[]="bit";
    int num=num_strlen(arr);//传入的是数组的首元素地址
    printf("长度为%d",num);
    return 0;
}

每次递归时,传入的字符串数都是一个,当传入的字符为'\0'就停止递归下去

这两题可能还是一些小可爱不怎么理解,我们就在来一题

练习3

n的阶乘

!n=n*(n-1)*...*1=n*!(n-1)

思路:

代码如下:

#include <stdio.h>
int My_num(int n)
{
  if (n == 1)
    return 1;
  else
  {
    return n * My_num(n - 1);
  }
}
int main()
{
  int n = 0;
  printf("输入你想计算的阶乘:(数字)");
  scanf("%d", &n);
  int num = My_num(n);//返回计算结果
  printf("%d的阶乘结果为:%d", n, num);
  return 0;
}

结果:

看到这里有些小可爱们有眉目了

那我们就开始练习一下斐波那契数。

斐波那契数:

1,1,2,3,5.........

从第三个数开始该数等于两数之和,2==1+1,3=2+1,5=3+2

思路:

我们主要捉住重点就是前两数之和等于第三个数 当我们要求出第几位的斐波那契数,我们只需求出前两数即可

代码如下:

#include <stdio.h>
int My_num(int n)
{
  if (n <= 2)
    return 1;
  else
    return My_num(n - 1) + My_num(n - 2);//记住My_num()输入位置返回该位置的斐波那契数,因为该位置的斐波那契数等于前两数之和,只需前两数之和就行
}
int main()
{
  int n = 0;
  printf("你要求出第几位的斐波那契数:>");
  scanf("%d", &n);
  int num = My_num(n);//传入n返回斐波那契数数
  printf("第%d位的斐波那契数为%d", n, num);
  return 0;
}

结果:

当我们输入越来越大的值就会发现,运行时间越来越长,因为递归也是有缺陷的,会重复大量的工作,这是使用递归不可避免的

#include <stdio.h>
int My_num(int n)
{
  int a = 1;
  int b = 1;
  while (n>2)
  {
    int d = a + b;
    a = b;
    b = d;
    n--;
  }
  return b;
}
int main()
{
  int n = 0;
  printf("你要求出第几位的斐波那契数:>");
  scanf("%d", &n);
  int num = My_num(n);//传入n返回斐波那契数数
  printf("第%d位的斐波那契数为%d", n, num);
  return 0;
}

9208a6526f6b441192d8c3d7afb5773d.png

这是非递归的,运行速度就很快

所以建议:

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

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

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

总结

递归总的来说是一种方法,在解决问题中我们要用最简单有效的方法进行解决问题,递归很好用,但使用要看场景

相关文章
|
6月前
什么是递归函数?怎样实现递归?
什么是递归函数?怎样实现递归?
|
10天前
|
JSON JavaScript 前端开发
除了递归比较,还有哪些方法可以进行深比较?
【10月更文挑战第29天】在实际应用中,可以根据具体的项目需求、数据结构特点以及性能要求等因素,选择合适的深比较方法。如果对性能要求不高且数据结构较简单,JSON序列化比较可能是一个简单有效的选择;如果需要处理复杂的数据结构和各种特殊情况,使用lodash或underscore.js等成熟的库可能更为可靠和便捷;而对于一些具有特殊比较逻辑的场景,则可以考虑编写自定义的比较函数。
|
1月前
|
算法 定位技术
数据结构与算法学习九:学习递归。递归的经典实例:打印问题、阶乘问题、递归-迷宫问题、八皇后问题
本文详细介绍了递归的概念、重要规则、形式,并展示了递归在解决打印问题、阶乘问题、迷宫问题和八皇后问题等经典实例中的应用。
37 0
|
3月前
|
算法
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
|
5月前
|
机器学习/深度学习 C语言
|
5月前
|
C语言
C语言函数递归详解:理解递归的原理与应用
C语言函数递归详解:理解递归的原理与应用
99 0
|
5月前
|
C语言
C语言学习记录——用递归思想求第n个斐波那契数,函数递归
C语言学习记录——用递归思想求第n个斐波那契数,函数递归
27 0
|
6月前
|
机器学习/深度学习 算法
加深理解函数递归
加深理解函数递归
|
12月前
二叉树相关问题细谈递归(下)
二叉树相关问题细谈递归(下)
61 0
|
12月前
|
存储
二叉树相关问题细谈递归(上)
二叉树相关问题细谈递归
69 0