当前位置: 首页 > news >正文

带你了解“函数递归”

目录

1. 什么是递归?

2. 函数递归的必要条件

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

代码如下:

2.2 编写一个函数,不用临时变量求字符串长度

代码如下:

2.3 递归与迭代

2.3.1 求n!(不考虑溢出)

代码如下:

2.3.2  求第n个斐波那契数(不考虑溢出)

代码如下


1. 什么是递归?

  • 程序调用自身的编程技巧称为i而递归(recursion)。
  • 递归作为一种算法再程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为为一个与原问题相似的规模较小的问题来求解,递归策略只需要只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
  • 递归的主要思考方式在于:大事化小

现在看这个概念可能有一点抽象,我们举一个最简单的例子:

int main()
{printf("LOVE YOU\n");main();//函数在里面自己调用自己就是递归return 0;
}

但是这个代码还是有一定的问题的:它会栈溢出

内存分为栈区、堆区和静态区,我们知道当我们调用函数时,它会在栈区申请空间。但是我们这个函数是无限循环的,它一直调用main函数,直到栈区没有空间了,它才停止。

 当然,这只是一个例子,我们在写代码的时候,不会这样写。

2. 函数递归的必要条件

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

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

例如:

输入:1234,输出:1 2 3 4.

我们可以先看看能不能计算:

1234%10=4(打印)

1234/10=123

123%10=3(打印)

123/10=12

12%10=2(打印)

12/10=1

1%10=1(打印)

这样虽然可以计算,但是顺序错了,用刚刚学的递归就可以解决(我们这里的限制条件是:只剩下个位数后不需要递归)

代码如下:

#include <stdio.h>void Print(unsigned int n)
{if (n > 9){Print(n / 10);}printf("%d ", n % 10);
}int main()
{unsigned int num = 0;scanf("%u", num);Print(num);return 0;
}

代码可能有些难理解,我们看下面的图:

递归的递是递推,就是上面的绿色箭头

递归的归是回归,就是上面的红色箭头

2.2 编写一个函数,不用临时变量求字符串长度

乍一看这个问题好像很难,没关系,我们先减小难度。编写一个函数求字符串长度

很简单对吧,我们再加一点难度:用调用函数写

arr[10]="a b c d e f \0 _ _ _"

  1. 首先我们要知道数组 arr 的指针就是第一个字母 a 的指针
  2. 当我们的指针 str 指向 a 时,我们记为 1 ,然后 str++,指针向下走指向 b ……最后当 str = ' \0 ' 时停止计数,所以这是一个循环。
  3. 定义一个计数变量 count ,每当进入循环 count++;str++;
  4. 当循环结束,返回 count  。
#include <stdio.h>
#include <string.h>int my_strlen(char* str)
{int count = 0;while (*str != '\0'){count++;str++;}return count;
}int main()
{char arr[10] = "abcdef";int len = my_strlen(arr);printf("%d\n", len);return 0;
}

理解之后我们进一步改良,使其符合题目:

题目不需要临时变量,count就不能用了。但是,我们还是之前的思路,只是用递归的方法:

首先,递归要有一个限制条件:指针不为 ' \0 '。满足这个条件后,指针+1,但是我们还要计数,直接返回的时候+1。否则,也就是说如果一开始就是 ' \0 ' ,那我们就直接返回0。

代码如下:

#include <stdio.h>
#include <string.h>int my_strlen(char* str)
{if (*str != '\0'){return 1 + my_strlen(str + 1);}elsereturn 0;
}int main()
{char arr[10] = "abcdef";int len = my_strlen(arr);printf("%d\n", len);return 0;
}

2.3 递归与迭代

循环是迭代的一种:

  1. 循环(loop),指的是在满足条件的情况下,重复执行同一段代码。比如,while语句。 循环则技能对应集合,列表,数组等,也能对执行代码进行操作。
  2. 迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。比如,for语句。 迭代只能对应集合,列表,数组等。不能对执行代码进行迭代。

2.3.1 求n!(不考虑溢出)

我们以前也写过求 n!  :

  • 主函数:输入n,定义ret接收调用函数 fac 的返回值,打印 ret 。
  • 调用函数:定义 i=1 和 ret=1 ,循环出 1 - n 的数,让 i <= n ,不断让 ret = ret * i 。
#include <stdio.h>int fac(int n)
{int i = 0;int ret = 1;for (i = 1; i <= n; i++){ret = ret * i;}return ret;
}int main()
{int n = 0;scanf("%d\n", &n);int ret=fac(n);printf("%d\n", ret);return 0;
}

除了这种循环(迭代)的写法,我们还可以改良一下,用递归写:fac(n) = n * fac(n-1)

  • 当 n <= 1 时,返回1
  • 当 n > 1 时,返回 n * fac(n-1)

代码如下:

int fac(int n)
{if (n <= 1)return 1;elsereturn n * fac(n - 1);}int main()
{int n = 0;scanf("%d", &n);int ret = fac(n);printf("%d", ret);return 0;
}

2.3.2  求第n个斐波那契数(不考虑溢出)

斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...

  • 这个数列从第3项开始,每一项都等于前两项之和。
  • 在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(≥ 2,∈ N*)

要写这个函数,首先我们要知道前两个数字,第三项开始就是前两项之和,我们只需要计算到 n * (n-1) 。

当 n <= 2 ,斐波那契数是 1 ;

当 n > 2 ,斐波那契数是前两项之和;

int Fib(int n)
{if (n <= 2)return 1;elsereturn Fib(n - 1) + Fib(n-2);
}int main()
{int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d", ret);return 0;
}

虽然这种方法可行,但是过程非常繁琐,当你输入的数字较大时需要递归很多次,有很多重复大量的计算。

递归虽然可行,但是有没有其他的更简单的方法,不用递归,直接从前往后算:前两个相加等于第三个;用迭代的方式计算:

代码如下:

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

相关文章:

带你了解“函数递归”

目录 1. 什么是递归&#xff1f; 2. 函数递归的必要条件 2.1 接收一个整型值&#xff08;无符号&#xff09;&#xff0c;按照顺序打印它的每一位。 代码如下&#xff1a; 2.2 编写一个函数&#xff0c;不用临时变量求字符串长度 代码如下&#xff1a; 2.3 递归与迭代 …...

网络资源面经2

文章目录Kafka 原理&#xff0c;数据怎么平分到消费者生产者分区消费者分区Flume HDFS Sink 小文件处理Flink 与 Spark Streaming 的差异&#xff0c;具体效果Spark 背压机制具体实现原理Yarn 调度策略Spark Streaming消费方式及区别Zookeeper 怎么避免脑裂&#xff0c;什么是脑…...

4年经验来面试20K的测试岗,一问三不知,我还真不如去招应届生。

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。看简历很多都是4年工作经验&#xff0c;但面试…...

K8S搭建NACOS集群踩坑问题

一、NACOS容器启动成功无法访问现象描述&#xff1a;通过K8S的statefulset启动&#xff0c;通过NodePort暴露不能在外网访问&#xff0c;只能在MASTER主节点访问。yaml配置&#xff1a;apiVersion: apps/v1 kind: StatefulSet metadata:name: nacos-${parameters.nameSpace}-dm…...

怎么避免计算机SCI论文的重复率过高? - 易智编译EaseEditing

论文成稿前 在撰写阶段就避免重复&#xff1a;在撰写阶段就避免文章中的重复内容&#xff0c;可以减少后期修改的工作量。 在写作前&#xff0c;可以制定良好的计划和大纲&#xff0c;规划好文章的结构和内容&#xff0c;从而减少重复内容。 加强对相关文献的阅读 为了避免自己…...

uni-app路由拦截

新建一个auth.js /** * description 权限存储函数 */ const authorizationKey Authorization export function getAuthorization() { return uni.getStorageSync(authorizationKey) } export function setAuthorization(authorization) { return uni.setStorageSync(aut…...

如何使用固态继电器实现更高可靠性的隔离和更小的解决方案尺寸

自晶体管发明之前&#xff0c;继电器就已被用作开关。从低压信号安全控制高压系统的能力&#xff0c;如隔离电阻监控&#xff0c;对于许多汽车系统的开发是必要的。虽然机电继电器和接触器的技术多年来有所改进&#xff0c;但设计人员要实现其终身可靠性和快速开关速度以及低噪…...

【YOLOv8/YOLOv7/YOLOv5系列算法改进NO.56】引入Contextual Transformer模块(sci期刊创新点之一)

文章目录前言一、解决问题二、基本原理三、​添加方法四、总结前言 作为当前先进的深度学习目标检测算法YOLOv8&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系列…...

深圳大学计软《面向对象的程序设计》实验3 指针2

A. 月份查询&#xff08;指针数组&#xff09; 题目描述 已知每个月份的英文单词如下&#xff0c;要求创建一个指针数组&#xff0c;数组中的每个指针指向一个月份的英文字符串&#xff0c;要求根据输入的月份数字输出相应的英文单词 1月 January 2月 February 3月 March …...

【基于机器学习的推荐系统项目实战-2】项目介绍与技术选型

本节目录一、项目介绍1.1 采用的数据源1.2 Concrec架构技术选型1.3 Sprak介绍1.4 Flink1.5 TensorFlow一、项目介绍 1.1 采用的数据源 Kaggle Anime Recommendations Dataset。 其中的动漫数据源自myanimelist.net。 1.2 Concrec架构技术选型 数据预处理模块&#xff1a;汇总…...

对称锥规划:锥与对称锥

文章目录对称锥规划&#xff1a;锥与对称锥锥的几何形状常用的指向锥Nonnegative Orthant二阶锥半定锥对称锥对称锥的平方操作对称锥的谱分解对称锥的自身对偶性二阶锥规划SOCP参考文献对称锥规划&#xff1a;锥与对称锥 本文主要讲锥与对称锥的一些基本概念。 基础预备&…...

4.基于Label studio的训练数据标注指南:情感分析任务观点词抽取、属性抽取

情感分析任务Label Studio使用指南 1.基于Label studio的训练数据标注指南&#xff1a;信息抽取&#xff08;实体关系抽取&#xff09;、文本分类等 2.基于Label studio的训练数据标注指南&#xff1a;&#xff08;智能文档&#xff09;文档抽取任务、PDF、表格、图片抽取标注等…...

算法拾遗二十五之暴力递归到动态规划五

算法拾遗二十七之暴力递归到动态规划七题目一【数组累加和最小的】题目二什么暴力递归可以继续优化暴力递归和动态规划的关系面试题和动态规划的关系如何找到某个问题的动态规划方式面试中设计暴力递归的原则知道了暴力递归的原则 然后设计常见的四种尝试模型如何分析有没有重复…...

Linux进程的创建结束类系统调用总结

tags: Linux OS Syscall C 写在前面 总结一下Linux系统的进程创建/终止/等待等系统调用, 参考: Linux/Unix系统编程手册. 下面主要给出例子, 关于函数原型可以参考书中或者man 2 syscall(例如man 2 fork). 测试环境: Ubuntu 20.04 x86_64 gcc-9 进程创建: fork() 用于创建…...

Git分支的合并策略有哪些?Merge和Rebase有什么区别?关于Merge和Rebase的使用建议

Git分支的合并策略有哪些&#xff1f;Merge和Rebase有什么区别&#xff1f;关于Merge和Rebase的使用建议1. 关于Git的一些基本原理1.1 Git的工作流程原理2. Git的分支合并方式浅析2.1 分支是什么2.2 分支的合并策略2.2.1 Three-way-merge&#xff08;三向合并原理&#xff09;2…...

2022-2-23作业

一、通过操作Cortex-A7核&#xff0c;串口输入相应的命令&#xff0c;控制LED灯进行工作 1.例如在串口输入led1on,开饭led1灯点亮 2.例如在串口输入led1off,开饭led1灯熄灭 3.例如在串口输入led2on,开饭led2灯点亮 4.例如在串口输入led2off,开饭led2灯熄灭 5.例如在串口输…...

1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取)、文本分类等

文本抽取任务Label Studio使用指南 1.基于Label studio的训练数据标注指南&#xff1a;信息抽取&#xff08;实体关系抽取&#xff09;、文本分类等 2.基于Label studio的训练数据标注指南&#xff1a;&#xff08;智能文档&#xff09;文档抽取任务、PDF、表格、图片抽取标注等…...

“高退货率”标签引热议,亚马逊跨境电商是好是坏?

在多数卖家不知情的情况下&#xff0c;亚马逊“高退货率”标签上线&#xff0c;该消息已被官方证实&#xff0c;目的是为了践行以客户为中心的理念和推动卖家提升服务。 官方确认上线“高退货率”标签 近期&#xff0c;有亚马逊卖家发现产品详情页出现了“高退货率”标签&…...

Pinia2

一、入门案例 1、安装 npm i pinia -S 2、注册插件 //main.ts import { createPinia } from pinia app.use(createPinia()) 3、创建store/countStore.ts import { defineStore } from "pinia"; const useCounterStore defineStore(counterStore,{ state(){ return{…...

服务器配置 | 在Windows本地打开服务器端Tensorboard结果

文章目录方法1&#xff1a;直接cmd使用ssh登录远程服务器方法2&#xff1a;利用Xshell设置本地端口进行监听方法3&#xff1a;利用MobaXterm设置本地端口监听这里介绍三个方法&#xff0c;在在Windows本地打开服务器端Tensorboard结果 方法1&#xff1a;直接cmd使用ssh登录远程…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...