你是真的“C”——详解函数递归+求解青蛙跳台阶问题

简介: C语言详解函数递归的运用
哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘

前言🙌

    哈喽各位友友们😊,我今天又学到了==很多有趣的知识==,现在迫不及待的想和大家分享一下!在学习C语言函数时,想必大家对函数递归这个模块的知识点还是感到比较玄妙的,我开始学函数递归的时候给我的感受就是它很奇妙,但是对它如何递?又如何归?的过程不是很了解。经过我这几天的刻苦学习,终于领悟到了它的精髓!本文的知识干货满满,千万不要错过哟!😍😍😍好啦,废话不多说,下面就带着大家学习函数递归的知识。😘

一、什么是递归🙌

什么是递归呢❓简单来说,程序调用自身的编程技巧称为递归(recursion)函数递归这种方法,通常把一个大型复杂的问题层层转化成一个与原问题相似的规模较小的问题来求解的递归策略。只需要少量的代码就可以描述出解题过程中所需要的大量的重复计算,大大减少了程序的代码量。递归的主要思考方式: ==把大事化小,函数从哪里调用就返回到哪里==。

二、递归运用的两个必要条件🙌

**1. 存在限制条件,当满足这个限制条件时,递归便不再继续。

  1. 每次递归调用之后越来越接近这个限制条件。**

   看着文字,大家可能还是感到有些困惑,接下来我举几个例子帮助大家更好的了解函数递归的这两个条件。😊
例一:接受一个整型值(无符号),按照顺序打印它的每一位。
例如:输入1234,输出1 2 3 4
画图分析:😍
在这里插入图片描述
在这里插入图片描述

解题代码: 😍

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void print(int n)
{
    if (n > 10)
    {
        print(n / 10);
    }
    printf("%d ", n % 10);
}
int main()
{
    int num = 1234;
    print(num);
    return 0;
}

运行结果:
在这里插入图片描述

例二:
编写一个函数不允许创建临时变量,求字符串的长度
画图分析:😍
在这里插入图片描述

在这里插入图片描述

解题代码:😍

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int  my_strlen(const char*str)
{
    if (*str == '\0')
    {
        return 0;
    }
    else
    {
        return my_strlen(str + 1) + 1;
    }
}
int main()
{
    char arr[] = "abcd";
    int len = my_strlen(arr);
    printf("%d", len);
    return 0;
}

运行结果
在这里插入图片描述
看了上面的代码,比起你写的非递归方式是不是在代码量上有所减少呢😃。哎呀,忙活了一个多小时,终于分析整理出来啦,只要大家能够看懂,理解递归调用的精髓就值啦!
这里小小总结一下吧:首先要知道函数递归的两个必要条件,然后真正了解到核心思想:大事化小,函数从哪里调用就返回到哪里。

三、递归与迭代🙌

虽然递归写出来可以减少代码量,但是它也有缺点。为什么这么说呢?接下来举一个经典的例子,大家就知道啦,废话不多讲,分析如下!🙌
例子:求第n个斐波那切数(不考虑溢出问题)

画图分析: 😍
在这里插入图片描述
解题代码:😍

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int fib(int n)
{
    if (n <= 2)
    {
        return 1;
    }
    else
    {
        return fib(n - 1) + fib(n - 2);
    }
}
int main()
{
    int n = 0;
    scanf("%d", &n);
    int num = fib(n);
    printf("第%d个斐波那契数为:%d", n, num);
    return 0;
}

测试代码,看看第10个斐波那契数是否为55:
在这里插入图片描述
这个例子是不考虑溢出的情况,所以只针对例子来说的话是没毛病的,但是==实际上它存在溢出的问题==。如果利用递归的方法的话,求第50个菲波那切数程序会消耗特别多的时间。我亲测是十分钟左右才跑出来。当求第10000个斐波那契数的时候,程序会崩掉。为什么会这样呢?我发现,在fib函数调用的时候,有很多重复的运算。如下图可知,当求第50个斐波那契数时,关于44这个的展开就已经重复出现很多次了,一直画下去的话,可想而知有多少数字是被重复展开计算的!
画图分析: 😍
在这里插入图片描述
因此,这里用非递归的方式来求解斐波那契数这个问题,效率更好,虽然递归代码看起来很少,但这里内部是进行很多运算的,很多重复的运算在里面,从而使栈溢出
非递归的方法实现: 😍
首选先定义三个变量,当n >= 2的时候,pre与next都是赋值为1,pre+next = resurt当n>2时,

画图分析:

在这里插入图片描述

非递归解题代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int fib(int n)
{
    int pre;
    int next = 1;
    int resurt = 1;
    while (n > 2)
    {
        n -= 1;
        pre = next;
        next = resurt;
        resurt = pre + next;
    }
    return resurt;
}
int main()
{
    int n = 0;
    scanf("%d", & n);
    int c = fib(n);
    printf("%d", c);
}

四、函数递归之青蛙跳台阶详解分析🙌

1、 青蛙跳台阶的问题是什么样的问题?😊

青蛙跳台阶问题简述: 😍
   ==一只青蛙可以一次跳 1 级台阶或一次跳 2 级台阶==。例如:跳上第一级台阶只有一种跳法:直接跳 1 级即可。跳上两级台阶,有两种跳法: 每次跳 1 级,跳两次; 或者一次跳 2 级。问要跳上第 n 级台阶有多少种跳法?

在这里插入图片描述

2、青蛙跳台阶的跳动图解:🙌

看了上述文字讲解,大家可能还是不够理解,这里已3层台阶为例,分析青蛙跳法和具体过程: 😍
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

   理清楚思路之后,我们不能发现,青蛙跳台阶的问题也是可以通过==函数递归==的方法来实现的。
青蛙跳台阶递归代码实现: 😍

int Frog(int n)
{
    if (n == 1)
        return 1;
    else if (n == 2)
        return 2;
    else if (n >= 3)
        return Frog(n - 1) + Frog(n - 2);
}
#include<stdio.h>
int main()
{

    int n = 0;
    scanf("%d", &n);
    int ways = Frog(n);
    printf("跳%d阶台阶方法总数为:%d\n", n, ways);
    return 0;
}

代码测试结果图: 😍
在这里插入图片描述
**当 n = 4时
Frog (4)
= Frog(3)+ Frog(2)

                                  = Frog (2) + Frog(1)+ Frog(2)
                                  = 2 + 1 +2
                                  = 5**

总结撒花💞

    许多问题是已递归的形式所解释的,这只是因为它比非递归的形式更为清晰。但是,这些问题的迭代实现往往比递归实现的效率更高,虽然代码的可读性稍微差些。所以对于递归的使用,要看具体问题具体分析,不要死用递归来解题。==本篇文章旨在带领大家学习函数递归的知识,== 如果我写的有什么的不好之处或者不足之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

相关文章
|
人工智能 分布式计算 大数据
超级计算与大数据:推动科学研究的发展
【9月更文挑战第30天】在信息时代,超级计算和大数据技术正成为推动科学研究的关键力量。超级计算凭借强大的计算能力,在尖端科研、国防军工等领域发挥重要作用;大数据技术则提供高效的数据处理工具,促进跨学科合作与创新。两者融合不仅提升了数据处理效率,还推动了人工智能、生物科学等领域的快速发展。未来,随着技术进步和跨学科合作的加深,超级计算与大数据将在科学研究中扮演更加重要的角色。
|
算法 调度 决策智能
基于自适应遗传算法的车间调度matlab仿真,可以任意调整工件数和机器数,输出甘特图
这是一个使用MATLAB2022a实现的自适应遗传算法解决车间调度问题的程序,能调整工件数和机器数,输出甘特图和适应度收敛曲线。程序通过编码初始化、适应度函数、遗传操作(选择、交叉、变异)及自适应机制进行优化,目标如最小化完工时间。算法在迭代过程中动态调整参数,以提升搜索效率和全局优化。
|
10天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
9天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
416 130
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
3天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
199 138
|
9天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
381 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
3天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
199 136
|
21天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1356 8