【C语言】——函数递归,用递归简化并实现复杂问题

文章目录

  • 前言
  • 一、什么是递归
  • 二、递归的限制条件
  • 三、递归举例
    • 1.求n的阶乘
    • 2. 举例2:顺序打印一个整数的每一位
  • 四、递归的优劣
  • 总结


前言

不多废话了,直接开始。


一、什么是递归

递归是学习C语言函数绕不开的⼀个话题,那什么是递归呢?
递归其实是⼀种解决问题的方法,在C语言中,递归就是函数调用自己。
写⼀个史上最简单的C语言递归代码:

#include <stdio.h>
int main()
{printf("hehe\n");main();//main函数中⼜调⽤了main函数return 0;
}

上述就是一个简单的递归程序,只不过上面的递归只是为了演示递归的基本形式,不是为了解决问题,代码最终也会陷入死递归,导致栈溢出(Stack overflow)。

在这里插入图片描述
递归的思想:
把一个大型复杂问题层层转化为⼀个与原问题相似,但规模较小的子问题来求解;直到子问题不能再被拆分,递归就结束了。所以递归的思考方式就是把大事化小的过程。

递归中的递就是递推的意思,归就是回归的意思,接下来慢慢来体会。


二、递归的限制条件

递归在书写的时候,有2个必要条件:

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

在下面的例子中,我们逐步体会这2个限制条件。


三、递归举例

1.求n的阶乘

计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘。

分析和代码实现:
我们知道n的阶乘的公式: n! = n ∗ (n − 1)!

举例:
5! = 5×4×3×2×1
4! = 4×3×2×1
所以:
5! = 5×4!

这样的思路就是把⼀个较大的问题,转换为⼀个与原问题相似,但规模较小的问题来求解的。

n!—> n*(n-1)!
(n-1)! —> (n-1)*(n-2)!

直到n是1或者0时,不再拆解

再稍微分析⼀下,当 n<=1 的时候,n的阶乘是1,其余n的阶乘都是可以通过上述公式计算。 n的阶乘的递归公式如下:
在这里插入图片描述
那我们就可以写出函数Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:

int Fact(int n)
{if(n<=0)return 1;elsereturn n*Fact(n-1);
}

测试:

#include <stdio.h>
int Fact(int n)
{if (n <= 0)return 1;elsereturn n * Fact(n - 1);
}
int main()
{int n = 0;scanf("%d", &n);int ret = Fact(n);printf("%d\n", ret);return 0;
}

运行结果(这里不考虑n太大的情况,n太大存在溢出):

在这里插入图片描述
画图推演:

在这里插入图片描述

2. 举例2:顺序打印一个整数的每一位

输入⼀个整数m,打印这个按照顺序打印整数的每⼀位。

比如:

输入:1234 输出:1 2 3 4
输入:520 输出:5 2 0

分析和代码实现:

这个题目,放在我们面前,首先想到的是,怎么得到这个数的每一位呢?
如果n是⼀位数,n的每⼀位就是n自己
n是超过1位数的话,就得拆分每⼀位

1234%10就能得到4,然后1234/10得到123,这就相当于去掉了4
然后继续对123%10,就得到了3,再除10去掉3,以此类推
不断的 %10 和 \10 操作,直到1234的每一位都得到;
但是这里有个问题就是得到的数字顺序是倒着的

但是我们有了灵感,我们发现其实⼀个数字的最低位是最容易得到的,通过%10就能得到那我们假设想写⼀个函数Print来打印n的每⼀位,如下表示:

Print(n)
如果n是1234,那表示为
Print(1234) //打印1234的每⼀位
其中1234中的4可以通过%10得到,那么
Print(1234)就可以拆分为两步:

  1. Print(1234/10) //打印123的每⼀位
  2. printf(1234%10) //打印4
    完成上述2步,那就完成了1234每⼀位的打印
    那么Print(123)⼜可以拆分为Print(123/10) + printf(123%10)

以此类推下去,就有

---- Print(1234)
==>Print(123) + printf(4)
==>Print(12) + printf(3)
==>Print(1) + printf(2)
==>printf(1)

直到被打印的数字变成⼀位数的时候,就不需要再拆分,递归结束。

代码展示:

void Print(int n)
{if (n > 9){Print(n / 10);}printf("%d ", n % 10);
}int main()
{int m = 0;scanf("%d", &m);Print(m);return 0;
}

输入和输出结果:

在这里插入图片描述
在这个解题的过程中,我们就是使用了大事化小的思路
把Print(1234) 打印1234每⼀位,拆解为首先Print(123)打印123的每⼀位,再打印得到的4
把Print(123) 打印123每⼀位,拆解为首先Print(12)打印12的每⼀位,再打印得到的3
直到Print打印的是⼀位数,直接打印就行。

画图推演:
在这里插入图片描述


四、递归的优劣

递归是⼀种很好的编程技巧,但它也有它的优点和缺点。

在C语言中每一次函数调用,都要需要为本次函数调用在栈区申请⼀块内存空间来保存函数调用期间的各种局部变量的值,这块空间被称为运行时堆栈,或者函数栈帧。

函数不返回,函数对应的栈帧空间就⼀直占用,所以如果函数调用中存在递归调用的话,每⼀次递归函数调用都会开辟属于自己的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。

所以如果采用函数递归的方式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出(stack overflow)的问题。

如果用不了递归,一般通常用迭代(循环)的方法。

事实上,我们看到的许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更加清晰, 但是这些问题的迭代实现往往比递归实现效率更高。

当⼀个问题非常复杂,难以使用迭代的方式实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。


往期文章:c语言如何生成随机数以及设置随机数的范围。(超详细)

总结

码字不易,点个关注和赞吧!!!
在这里插入图片描述

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

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

相关文章

电商平台商品销量API接口,30天销量API接口接口超详细接入方案说明

电商平台商品销量API接口的作用主要是帮助开发者获取电商平台上的商品销量信息。通过这个接口&#xff0c;开发者可以在自己的应用或网站中实时获取商品的销量数据&#xff0c;以便进行销售分析、库存管理、市场预测等操作。 具体来说&#xff0c;电商平台商品销量API接口的使…

RocketMq集成SpringBoot(待完善)

环境 jdk1.8, springboot2.7.3 Maven依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version><relativePath/> <!-- lookup parent from…

Unity中后处理简介

文章目录 前言一、后处理的原理二、我们看一下Unity文档中&#xff0c;内置的后处理前后的效果后处理前&#xff1a;后处理后&#xff1a; 前言 我们在这篇文章中&#xff0c;了解一下Unity中的后处理效果 后期处理概述 一、后处理的原理 在后处理的过程中&#xff0c;我们主…

Java当中常用的算法

文章目录 算法二叉树左右变换数据二分法实现 冒泡排序算法插入排序算法快速排序算法希尔排序算法归并排序算法桶排序算法基数排序算法分治算法汉诺塔问题动态规划算法引子代码实现背包问题 KMP算法什么是KMP算法暴力匹配KMP算法实现 今天我们来看看常用的算法&#xff0c;开干。…

《微信小程序开发从入门到实战》学习四十五

4.4 云函数 云函数是开发者提前定义好的、保存在云端并且将在云端运行的JS函数。 开发者先定义好云函数&#xff0c;再使用微信开发工具将云函数上传到云空间&#xff0c;在云开发控制台中可看到已经上传的云函数。 云函数运行在云端Node.js环境中。 小程序端通过wx.cloud.…

IP地址定位技术为网络安全建设提供全新方案

随着互联网的普及和数字化进程的加速&#xff0c;网络安全问题日益引人关注。网络攻击、数据泄露、欺诈行为等安全威胁层出不穷&#xff0c;对个人隐私、企业机密和社会稳定构成严重威胁。在这样的背景下&#xff0c;IP地址定位技术应运而生&#xff0c;为网络安全建设提供了一…

短视频ai剪辑分发矩阵系统源码3年技术团队开发搭建打磨

如果您需要搭建这样的系统&#xff0c;建议您寻求专业的技术支持&#xff0c;以确保系统的稳定性和安全性。 在搭建短视频AI剪辑分发矩阵系统时&#xff0c;您需要考虑以下几个方面&#xff1a; 1. 技术实现&#xff1a;您需要选择适合您的需求和预算的技术栈&#xff0c;例如使…

肖sir__ 项目讲解__项目数据

项目时间&#xff1a; 情况一&#xff1a;项目时间开始到上线的时间&#xff0c;这个时间一般比较长&#xff08;一年&#xff0c;二年&#xff0c;三年&#xff09; 情况二&#xff1a;项目的版本的时间或则是周期&#xff08;1个月&#xff0c;2个月&#xff0c;3个月&…

机器人、智能小车常用的TT电机/310电机/370电机选型对比

在制作智能小车或小型玩具时&#xff0c;在电机选型上一些到各种模糊混淆的概念&#xff0c;以及各种错综复杂的电机参数&#xff0c;本文综合对比几种常用电机的参数及特性适应范围&#xff0c;以便快速选型&#xff0c;注意不同生产厂家的电机参数规则会有较大差异。 普通TT…

论文阅读:PointCLIP: Point Cloud Understanding by CLIP

CVPR2022 链接&#xff1a;https://arxiv.org/pdf/2112.02413.pdf 0、Abstract 最近&#xff0c;通过对比视觉语言预训练(CLIP)的零镜头学习和少镜头学习在2D视觉识别方面表现出了鼓舞人心的表现&#xff0c;即学习在开放词汇设置下将图像与相应的文本匹配。然而&#xff0c;…

【ET8】2.ET8入门-ET框架解析

菜单栏相关&#xff1a;ENABLE_DLL选项 ET->ChangeDefine->ADD_ENABLE_DLL/REMOVE_ENABLE_DLL 一般在开发阶段使用Editor时需要关闭ENABLE_DLL选项。该选项关闭时&#xff0c;修改脚本之后&#xff0c;会直接重新编译所有的代码&#xff0c;Editor在运行时会直接使用最…

免费网页抓取工具大全【附下载和工具使用教程】

在当今信息爆炸的时代&#xff0c;获取准确而丰富的数据对于企业决策和个人研究至关重要。而网页抓取工具作为一种高效获取互联网数据的方式&#xff0c;正逐渐成为大家解决数据需求的得力助手。本文将深入探讨网页抓取工具的种类&#xff0c;并为大家提供简单实用的页面采集教…

windows安装protoc、protoc-gen-go、protoc-gen-go-grpc

文章目录 一、 protoc二、protoc-gen-go三、protoc-gen-go-grpc 一、 protoc 1&#xff0c;下载&#xff1a;https://github.com/google/protobuf/releases 下载对应的protoc&#xff0c;注意选择windows 2&#xff0c;下好之后解压就行&#xff0c;然后把bin目录加入到环境…

【异常】浅析异常体系及为什么一定会执行finally块代码

异常体系&#xff1a; &#xff08;1&#xff09;所有异常&#xff08;Exception&#xff09;、错误&#xff08;Error&#xff09;都继承自异常中的基类&#xff1a;Throwable。而异常又可以分为检查异常&#xff08;Checked Exception&#xff09;、非检查异常&#xff08;Un…

msvcp100.dll丢失的常见原因/msvcp100.dll丢失的解决方法分享

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp100.dll丢失”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;给使用者带来了很大的困扰。那么&#xff0c;究竟是什么原因导致了msvcp100.dll文件的丢失呢&#xff1f;本…

STM32F1之CAN介绍

目录 ​编辑 1. CAN 是什么&#xff1f; 2. 总线拓扑图 3. CAN 的特点 4. CAN 协议的基本概念 1. CAN 是什么&#xff1f; CAN 是 Controller Area Network 的缩写&#xff08;以下称为 CAN&#xff09;&#xff0c;是 ISO*1 国际标准化的串行通信协议。 在当前的汽车产…

javaWebssh学生系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh学生管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,My…

python:mplfinance 画K线图+布林线

pip install mplfinance ; python 安装使用 TA-lib 安装主要在 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 这个网站找到 TA_Lib-0.4.24-cp310-cp310-win_amd64.whl pip install /pypi/TA_Lib-0.4.24-cp310-cp310-win_amd64.whl 编写 mpf_kline_boll.py 如下 # -*- cod…

【VRTK】【VR开发】【Unity】12-占位身体

课程配套学习资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【概要】 目前你会发现,就算存在非Trigger Collider的墙壁屏障等,也能够正常穿过,这会导致不沉浸的体验。你需要一个占位身体来实现让墙壁等碰撞并挡住自己…

`Numpy`数组中 数据的修改(第10讲)

Numpy数组中 数据的修改(第10讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ…