C语言函数递归

前言与概述

本文章将通过多个代码并赋予图示,详细讲解C语言函数递归的定义和函数递归的运算过程。

函数递归定义

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

最简单的递归

在main()函数体内调用main()函数,这是最简单的函数递归。当然,这样的函数递归是错误的,因为main()函数被不断的调用,导致陷入死递归。

示例代码:

//最简单的函数递归
#include <stdio.h>
int main()
{printf("Good!!\n");main();return 0;
}

运行结果:

栈溢出

Stack overflow:栈溢出。在计算机内存中,主要分为三大区:栈区、堆区、静态区。栈区存放着局部变量、函数形参、函数返回值等临时性变量。堆区主要用于动态内存分配。静态区主要存放全局变量和静态变量。如果我们把栈区单独拿出,当程序进入main()函数中,main()函数会向栈区申请空间,于是,main()函数会得到一片空间,称为main()函数的栈帧空间。在main()函数体内定义的局部变量会存放在main()函数的栈帧空间里。如果main()函数调用了函数,调用的这个函数同样也会向栈区申请空间。但是栈区的空间是有限的,如果不停的调用函数,就会不停的占用栈区空间,直到栈区空间被耗尽,就会导致栈溢出。当函数完成调用,就会自动销毁,并释放空间。

打印一个数的每一位

算法

现在有一个整数1234,按照顺序打印这个数的每一位。

整数1234最容易打印的数是4,只需要将这个整数模10(%10)就可以得到。然后将整数1234除10,就可以去掉最后一位数字。接着将得到的整数123模10,打印得到的数字3。再将这个整数除以10,去掉最后一位3,得到整数12。以此类推,当这个整数小于10,就可以直接打印。

% 10 用于得到最后一位;/ 10 用于去掉最后一位。

定义一个函数,用于打印整数的每一位;定义变量number将读取的数值作为实参传给函数。函数会通过对10取模,打印整数的最后一位。接着将整数的值除以10,作为新的实参传给函数。如果整数的值大于9,就重复执行打印、调用函数。否则,只打印不调用函数。

如果函数体内先打印后调用函数,得到的结果就是将原整数逆序打印。

所以可以先调用函数后打印,这样得到的结果就是将原整数顺序打印。

示例代码

//先调用后打印
#include <stdio.h>
void print(int x)
{if (x > 9){print(x / 10);printf("%d ", x % 10);}else{printf("%d ", x);}
}
int main()
{int number = 0;scanf("%d", &number);print(number);return 0;
}

运行结果

 

 函数递归运行过程

 如果我们想在屏幕上按顺序打印整数123的每一位。在控制台上输入数字123,scanf()函数读入用户输入的数值,并赋予变量number。main()函数调用print()函数,把变量number的值作为形参传给print()函数(步骤1)。此时形参x的值是123。x的值大于9,条件成立,将变量x的值除以10的结果作为实参传给print()函数(步骤2)。此时,形参x的值是12,大于9,条件成立,将变量x的值除以10的结果作为实参传给print()函数(步骤3),此时,形参x的值是1,条件不成立。在屏幕上打印变量x的值1。遵循着“从哪里来回到那里去”的原则,返回到上一个函数(步骤4),并直接向下执行,此时,形参x的值是12,在屏幕上打印数字2,并返回到上一个函数(步骤5)此时,形参x的值是123,在屏幕上打印数字3。返回到main()函数(步骤六)。

求n的阶乘

算法

一个数的阶乘就是从1开始,每次乘的数都比上一个乘的数多一,直到乘的数等于它本身。0的阶乘等于1。如4的阶乘就等于1*2*3*4=24。下面设计一个函数,用于根据用户输入的值,求出对应的阶乘。

如果用户输入的数小于等于1,那么n的阶乘就是1;否则,n的阶乘就是n *(n - 1)的阶乘。

示例代码:

//求n的阶乘
#include <stdio.h>
int times(int x)
{if (x <= 1){return 1;}else{return x * times(x - 1);}
}
int main()
{int number = 0;scanf("%d", &number);int result = times(number);printf("%d", result);return 0;
}

运行结果

 

函数递归调用过程 

如果我们想知道3的阶乘,在控制台中输入数字3。scanf()函数从控制台中读取数字3,并赋予变量number。定义变量result,调用times()函数,将变量number的值作为实参传给函数(步骤一)。形参x得到变量number的值3。形参x的值大于1,条件不成立。调用times()函数,并将x - 1的值作为新的实参传给times()函数(步骤2)。此时形参x的值是2,条件不成立,调用times()函数,并将x - 1的值作为新的实参传给times()函数(步骤3)。此时形参x的值是1,条件成立,返回数字1。返回到上一个函数(步骤4),计算x * 1(2 * 1)的值并返回到上一个函数(步骤5)。函数得到返回值2,并将x * 2(3 * 2)的值返回到原调用函数处(步骤6)。变量result得到返回值6,并打印变量result的值。

递归与迭代

区别

迭代具有运行效率高的优点,但是代码量相对较大。递归整体上代码更加简洁,可读性高,但是可能出现栈溢出、运行效率低等问题。

求第n个斐波那契数(递归)

计算方法

什么是斐波那契数列?

1  1   2   3   5   8   13   21   34   55

斐波那契数列的第n个数(n >= 3)等于前两个数之和。

如果n的值小于等于2,那斐波那契数是1,如果n的值大于2,那么该斐波那契数等于第n - 1的斐波那契数加上第n - 2的斐波那契数。

示例代码(递归实现)

//求第n个斐波那契数
#include <stdio.h>
int fib(int x)
{if (x <= 2){return 1;}else{return fib(x - 1) + fib(x - 2);}
}
int main()
{int number = 0;scanf("%d", &number);int result = fib(number);printf("%d", result);return 0;
}

 运行结果 (递归实现)

不足之处 

虽然使用递归可以求出第n个斐波那契数,但如果输入n的值较大,就可能需要计算很长时间,甚至会导致程序崩溃。这主要是因为代码进行大量重复多余的计算。比如求第40个斐波那契数,仅第3个斐波那契数就重复计算了39088168次。于是,我们可以使用迭代来快速寻找到想要的值。

示例代码(迭代实现)

//求第n个斐波那契数非递归
#include <stdio.h>
int main()
{int number = 0;scanf("%d",&number);int a = 1;int b = 1;int c = 0;int temp = number;if (temp <= 2){c = 1;}else{while (temp - 2 >= 1){c = a + b;a = b;b = c;temp = temp - 1;}}printf("%d", c);return 0;
}

运行结果 (迭代实现)

代码分析

定义变量a保存第一个元素,定义变量b保存第二个元素,定义变量c保存第三个元素。如果输入的值小于等于2,那么变量c的值就是2。如果输入的值大于2,那么变量c的值就等于变量a的值加上变量b的值。把变量b的值赋予变量a,变量a就成为新的第一个元素,把变量c的值赋予变量b,变量b就成为新的第二个元素。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/408393.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM agentic模式之规划能力(planning)

文章目录 任务分解分解优先方法交替分解方法 多计划选择外部规划器辅助规划反思和改进记忆增强规划评估 2024年2月的综述《 Understanding the planning of LLM agents: A survey》提供了基于LLM的的agent的规划(planning)能力的系统视角&#xff0c;总结了近年来提高规划能力…

EmguCV学习笔记 VB.Net 6.4 霍夫变换

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

基于x86 平台opencv的图像采集和seetaface6的人脸朝向姿态估计功能

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境三、开发流程3.1 编写测试3.2 配置资源文件3.2 验证功能一、概述 本文档是针对x86 平台opencv的图像采集和seetaface6的人脸朝向姿态估计功能,opencv通过摄像头采集视频图像,将采集的视频图像送给seetaface6的人脸朝向姿态…

Telnet不止于端口测试:探索经典工具的多样化应用

文章目录 Telnet详解与实用指南1. 引言2. Telnet 的安装和启动2.1 在 Windows 上安装 Telnet2.2 在 Linux 上安装 Telnet2.3 在 macOS 上使用 Telnet 3. Telnet 的基本命令与操作3.1 远程登录3.2 测试端口连通性3.3 调试网络服务3.4 网络协议调试3.5 简单的文件传输 4. Telnet …

sklearn中的线性回归

多元线性回归 指的 是一个样本 有多个特征的 线性回归问题。 w 被统称为 模型的 参数&#xff0c;其中 w0 被称为截距&#xff08;intercept&#xff09;&#xff0c;w1~wn 被称为 回归系数&#xff08;regression coefficient&#xff09;。这个表达式和 yazb 是同样的…

Web前端性能优化合集

简介 自互联网兴起以来&#xff0c;从最初的静态网页到如今的动态交互、单页应用&#xff08;SPA&#xff09;、PWA&#xff08;Progressive Web Apps&#xff09;等&#xff0c;互联网技术正在飞速发展&#xff0c;随着用户体验成为核心竞争力之一&#xff0c;前端性能直接影…

【Midjourney】Midjourney全面开放网站版,所有用户每天可免费生成25次

Midjourney一直作为AI文生图领域的龙头老大&#xff0c;最近对面对市场上日益增长的竞争压力&#xff0c;尤其是来自 Flux 的挑战&#xff0c;终于向所有用户开放官方网站。尽管还处于早期阶段&#xff0c;但为了吸引更多用户体验&#xff0c;它暂时是完全免费的。 下面是Midj…

什么是d3dx9_42.dll?如何将丢失的d3dx9_42.dll进行修复呢?

d3dx9_42.dll文件丢失什么情况&#xff1f;如何将丢失的d3dx9_42.dll进行修复呢&#xff1f;d3dx9_42.dll又是什么文件&#xff1f;d3dx9_42.dll 文件是一个由 Microsoft Corporation 开发的部分&#xff0c;属于 Microsoft DirectX for Windows 的一组庞大库集合中的一个。Dir…

Android系统架构

文章目录 Android系统架构Android四层架构01.Linux内核层02.系统运行库层03.应用框架层04.应用层 Android应用开发特色01.四大组件02.丰富的系统控件03. SQLite数据库04.强大的多媒体05.地理位置定位 Android系统架构 为了让你能够更好地理解Android系统是怎么工作的&#xff…

HashMap 的实现原理

说一下 HashMap 的实现原理&#xff1f; JDK1.7 HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元&#xff0c;每一个Entry包含一个key-value键值对。&#xff08;其实所谓Map其实就是保存了两个对象之间的映射关系的一种集合&#xff09;&#xff0c;其中Key 和…

PDPS软件 那智机器人 (丰田版)离线程序导出处理

在PDPS仿真软件中导出的那智机器人离线程序&#xff0c;一般是无法直接给TFD控制装置-那智机器人&#xff08;丰田式样版&#xff09;导入及识别使用。因此要对导出的程序进行转换编译处理&#xff0c;才能给TFD那智机器人&#xff08;丰田式样版&#xff09;导入离线程序。以下…

Java共享内容通信 VS Golang通信共享内存

接触的编程语言从C到Java再到现在Go&#xff0c;每个语言都有其独有特性&#xff0c;也具备共通之处。 最近在学习并发编程的时候&#xff0c;发现一个很有意思的点&#xff1a;Java基于共享共享内存通信&#xff0c;而Golang则是通过通信共享内存。为什么&#xff1f;下面我们…

自定义@ResponseBody以及SpringMVC总结

文章目录 1.需求分析2.目录3.自定义ResponseBody注解4.MonsterController.java5.Monster.java 实现序列化接口6.引入jackson7.Adapter.java 如果有ResponseBody注解就返回json8.测试9.SpringMVC执行流程 1.需求分析 2.目录 3.自定义ResponseBody注解 package com.sunxiansheng…

简单实现进度条效果(vue2)

如果用echarts或者其他图表来写个进度条有点大材小用&#xff0c;所以直接简单html、js写一下就可以&#xff1b; 以下代码基于vue2&#xff0c; 部分代码来自国内直连GPT/Claude镜像站 <template><div class"progress-container"><div class"p…

springboot框架中filter过滤器的urlPatterns的匹配源码

如下图所示&#xff0c;我使用WebFilter注解的方式定义了一个过滤器&#xff0c;同时定义了过滤器的过滤条件 urlPatterns为/*,可能很多人都知道filter的/*代表所有URL都匹配&#xff0c;但是源码在哪里呢 先打断点看一下调用链 然后跟着调用链慢慢点&#xff0c;看看哪里开始…

【Material-UI】深入了解Radio Group中的useRadioGroup Hook

文章目录 一、什么是useRadioGroup&#xff1f;1.1 Hook的返回值 二、useRadioGroup的基本用法2.1 代码示例2.2 代码解析 三、useRadioGroup的应用场景3.1 动态样式调整3.2 高级交互逻辑 四、使用useRadioGroup的最佳实践4.1 保持代码简洁4.2 结合主题定制4.3 注意无障碍设计 五…

【论文分享】Graviton: Trusted Execution Environments on GPUs 2018’OSDI

目录 AbstractIntroductioncontributions BackgroundGPUSoftware stackHardwareContext and channel managementCommand submissionProgramming modelInitializationMemory allocationHost-GPU transfersKernel dispatch Sharing Intel SGX Threat ModelOverviewGraviton Archi…

【动态规划】第 N 个泰波那契数

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 题目讲解算法原理代码实现 题目 题目如下&#xff1a; 讲解算法原理 我们先说一下动态规划题目的整体做题思路&#xff1a; 第一步&#xff1a; 状态表示 什么是状态表示? 做动态规划类题目一般…

appium学习记录

免责声明 本文内容仅供参考&#xff0c;将appuim与爬虫技术相结合可能违反某些app的使用条款和法律法规。作者不对因此产生的法律问题或技术风险负责。建议读者在进行爬取操作前&#xff0c;充分了解相关法律法规并确保合规。 1、初识appium 背景&#xff1a;部分APP需要反编译…

<数据集>遥感船舶识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;15047张 标注数量(xml文件个数)&#xff1a;15047 标注数量(txt文件个数)&#xff1a;15047 标注类别数&#xff1a;25 标注类别名称&#xff1a;[Aircraft Carrier, Auxiliary Ships, Other Ship, Other Warship,…