C语言中的套娃——函数递归

news2024/12/25 22:40:46

目录

一、什么是递归

1.1.递归的思想

1.2.递归的限制条件

二、举例体会

2.1.求n的阶乘 

2.2.顺序打印整数的每一位

2.3.斐波那契数列

三、递归与迭代


一、什么是递归

在学习C语言的过程中,我们经常会跟递归打交道,什么是递归呢?它其实是一种解决问题的方法,递归递归,顾名思义,递推回归。在C语言中,函数自己调用自己就是递归,我们可以把它想成生活中的俄罗斯套娃。

下面请看最简单的递归代码:

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

在上面的代码中,我们看到了main函数里再次调用了main函数,我们可以想象,这个程序会一直调用下去,直到,内存不够导致栈溢出(Stack overflow)。

1.1.递归的思想

递归的思想用一个词来讲就是“大事化小”。

其中代表递推代表回归。

1.2.递归的限制条件

刚刚我们看到,一直调用main函数的话,会造成死递归,因此,我们在使用递归时需要注意一些必要条件。

1.递归存在限制条件,当超过这个限制条件时递归就应该停止

2.每次递归应该越来越接近这个限制条件。 

接下来我们举几个例子来让大家体会一下这两个必要条件。

二、举例体会

2.1.求n的阶乘 

⼀个正整数的阶乘(factorial)是所有⼩于及等于该数的正整数的积,并且0的阶乘为1。
 
自然数n的阶乘写作 n! 。

经分析可知n! = n * (n-1) * (n-2)... * 3 * 2 * 1,而(n-1)! = (n-1) * (n-2) *...* 3 * 2 * 1。

所以n! = n * (n-1)!。

我们要求n的阶乘,只需要求n和n-1的阶乘的乘积,问题也就变成了求n-1的阶乘。经过一次递归,我们就从n变到n-1,那递归的次数足够了,我们就可以到最后的1的阶乘。那怎么得到n的阶乘呢,我们刚刚一步一步得到1的阶乘,那我们再一步一步乘回去,最终得到n的阶乘。

上述思路就是所谓的递归,也就是把一个较大的问题转换为与原问题相似的小问题。

当n = 0时,n! = 1。我们可以得到递推公式:

代码如下:

函数部分

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

总体

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

测试结果

2.2.顺序打印整数的每一位

输入一个整数n,顺序打印其每一位。

input : 1234

output : 1 2 3 4

分析可知,1234/10 = 123,而1234%10 = 4。那我们可以巧妙的利用上述特性,得到1234的每一位。但是出现一个问题,我们获得的数字的顺序是倒着的,这该怎么办呢。我们可以仔细品味一下递归,递推和回归,先递推再回归。

我们就可以先进行/10的操作,再打印%10的余数,如下:

void Print(int n)
{
 if(n>9)
 {
     Print(n/10);
 }
 printf("%d ", n%10);
}

画图推演一下:

代码如下:

#include<stdio.h>
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;
}

运行结果:

2.3.斐波那契数列

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称“兔子数列”,其数值为:1、1、2、3、5、8、13、21、34…… 

其递推公式为

用递推写出代码很简单:

#include<stdio.h>

int Fib(int n) 
{
	if (n == 1 || n == 2)
		return 1;
	else 
		return Fib(n - 1) + Fib(n - 2);
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	printf("%d", Fib(n));
	return 0;
}

运行结果:

那如果让你不用递归的方法,你会怎么做呢? 

我们可以创建三个变量,就像两个数互相交换那样,将a赋值1,b赋值1,c为a与b的和。

n大于二之后才开始循环,所以我们可以这么写:

int Fib(int n) 
{
	int a = 1, b = 1,c = 0;
	
	while (n>2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return b;
}

 一个接着一个交换值,直到n等于2,退出循环,此时c的值赋给了b,而我们在n小于等于2的时候,求不出来c,而b的值正好是1,所以我们返回b的值。

三、递归与迭代

上面我们说了什么是递归,这又来个迭代,什么叫迭代呢?说白了通常就是循环。

比如刚才计算阶乘,我就不想用递归,那我就循环n次,也可以解决问题,并且该方法效率比递归高。

我们遇到的许多问题用递归解释的原因是因为,它比非递归好想好解释,但这些问题往往迭代比递归的效率更高。

我们说当一个问题非常复杂,难以用迭代的方式来解决时2,这时候递归实现的简洁性便可以补偿运行时的开销。

就像刚刚的例三,求斐波那契数列,使用迭代的方法就更加有效率。

如图所示,递归层次越深,冗余计算越多,我们可以简单测试一下

#include <stdio.h>
int count = 0;
int Fib(int n)
{
 if(n == 3)
 count++;//统计第3个斐波那契数被计算的次数
 if(n<=2)
 return 1;
 else
 return Fib(n-1)+Fib(n-2);
}
int main()
{
 int n = 0;
 scanf("%d", &n);
 int ret = Fib(n);
 printf("%d\n", ret); 
 printf("\ncount = %d\n", count);
 return 0;
}

 来看结果

这才是40,可想而知50会是多大的天文数字。

而迭代的方式,我们只需要前后一步一步相加即可。


最后总结一下,递归是一个很好的解决问题方式,在编程学习中,我们会经常用到它,但是它也不是万能的,还是需要我们多动脑思考。

我相信,我们总会找到解决办法的。

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

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

相关文章

用于自监督视觉预训练的屏蔽特征预测

Masked Feature Prediction for Self-Supervised Visual Pre-Training 一、摘要 提出了用于视频模型自监督预训练的掩模特征预测&#xff08;MaskFeat&#xff09;。首先随机屏蔽输入序列的一部分&#xff0c;然后预测屏蔽区域的特征。研究了五种不同类型的特征&#xff0c;发…

vue3 + TS + vite 搭建中后台管理系统(开箱即用)

[TOC](vue3 TS vite 搭建中后台管理系统) 开箱即用 前言 要成功&#xff0c;先发疯&#xff0c;头脑简单往前冲&#xff01; 三金四银&#xff0c;金九银十&#xff0c;多学知识&#xff0c;也不能埋头苦干&#xff0c;要成功&#xff0c;先发疯&#xff0c;头脑简单往前冲…

Java计划线程池ScheduledThreadPoolExecutor运行流程和源码分析

1. 计划线程池ScheduledThreadPoolExecutor简介 ScheduledThreadPoolExecutor继承自线程池ThreadPoolExecutor&#xff0c;并在其基础上增加了按时间调度执行任务的功能&#xff0c;如果对ThreadPoolExecutor还不是很熟悉&#xff0c;可以阅读一下这篇文章&#xff1a; Java线…

成都东部新区文化旅游体育局莅临国际数字影像产业园参观入驻企业,共促政产交流“零距离”

2月23日&#xff0c;成都东部新区文化旅游体育局投服处处长田东一行莅临国际数字影像产业园考察交流&#xff0c;树莓科技&#xff08;成都&#xff09;集团有限公司副总裁吴晓平、行政运营经理郭宇风、国际数字影像产业园项目负责人万里全程接待。 吴晓平副总带领田东处长一行…

开发知识点-.netC#图形用户界面开发之WPF

C#图形用户界面开发 框架简介WinForms(Windows Forms):WPF(Windows Presentation Foundation):UWP(Universal Windows Platform):MAUI(Multi-platform App UI):选择控件参考文章随笔分类 - WPF入门基础教程系列基于C#语言的GUI开发,主要介绍WPF框架

CAD怎么绘制建筑平面图纸?

CAD沪指图纸很简单&#xff0c;想要绘制一个简单的建筑图纸&#xff0c;该怎么绘制建筑平面图呢&#xff1f;下面我们就来看看详细的教程。 1、首先&#xff0c;运用绘图功能中的直线按照比例尺寸绘制出轴网。轴网绘制我们一般将轴网的颜色选择为红色&#xff0c;轴网的线型选择…

jdk21本地执行flink出现不兼容问题

环境说明&#xff1a;换电脑尝尝鲜&#xff0c;jdk&#xff0c;flink都是最新的&#xff0c;千辛万苦把之前的项目编译通过&#xff0c;跑一下之前的flink项目发现启动失败&#xff0c;啥都不说了上异常 Exception in thread "main" java.lang.IllegalAccessError: …

一次奇怪的事故:机器网络连接打满,导致服务不可用

业务背景 发生事故的业务系统是一个toB业务&#xff0c;业务是服务很多中小企业进行某项公共信息指标查询。系统特点:业务处理相对简单&#xff0c;但是流量大&#xff0c;且对请求响应要求较高&#xff1a; 业务请求峰值qps达50w&#xff0c;平时流量达20w左右。 请求响应时…

18 SpringMVC实战

18 SpringMVC实战 1. 课程介绍2. Spring与Spring MVC环境配置 1. 课程介绍 2. Spring与Spring MVC环境配置

Nginx之rewrite重写功能

一、rewrite概述 1、rewrite功能 访问重写 rewrite 是 Nginx HTTP 请求处理过程中的一个重要功能&#xff0c;它是以模块的形式存在于代码中的&#xff0c;其功能是对用户请求的 URI 进行 PCRE 正则重写&#xff0c;然后返回 30 重定向跳转或按条件执行相关配置。 Nginx服务…

JSON简介以及如何在Python中使用JSON

什么是JSON&#xff1f; JSON是"JavaScript Object Notation"的简称&#xff0c;是一种数据交换格式 JSON格式 假设我们有一个对象&#xff0c;这个对象有两个属性&#xff1a;“name”跟“age”。 在JSON中是这样表达的&#xff1a; { "name":"男孩…

51.仿简道云公式函数实战-文本函数-JOIN

1. JOIN函数 JOIN 函数可通过连接符将数组的值连成文本。 2. 函数用法 JOIN(数组,"连接符") 3. 函数示例 如需将复选框中勾选的选项通过”-“组合在一起&#xff0c;则可设置公式为JOIN(复选框组,"-") 4. 代码实战 首先我们在function包下创建text包…

用户态协议栈01-udp收发

文章目录 用户态协议栈01-udp收发前期准备DPDK初始化开始搓udp协议栈配置dpdk定义udp相关变量接受udp数据&&读取包内容接口层拼接udp数据包完整代码 如何启动实验如何编译使用效果 用户态协议栈01-udp收发 实现用户态协议栈最最简单的就是实现Udp的收发&#xff0c;下…

高性能API云原生网关 APISIX安装与配置指南

Apache APISIX是Apache软件基金会下的顶级项目&#xff0c;由API7.ai开发并捐赠。它是一个高性能的云原生API网关&#xff0c;具有动态、实时等特点。 APISIX网关可作为所有业务的流量入口&#xff0c;为用户提供了丰富的功能&#xff0c;包括动态路由、动态上游、动态证书、A…

将SU模型导入ARCGIS,并获取高度信息,多面体转SHP文件(ARCMAP)

问题:将Sketchup中导出的su模型,导入arcgis并得到面shp文件,进而获取各建筑的高度、面积等信息。 思路: (1)导入arcgis得到多面体 (2)转为面shp文件 (3)计算高度/面积等 1、【3D Analyst工具】【转换】【由文件转出】【导入3D文件】(在此步骤之间,建议先建立一个…

flink学习之旅(二)

目前flink中的资源管理主要是使用的hadoop圈里的yarn&#xff0c;故此需要先搭建hadoop环境并启动yarn和hdfs&#xff0c;由于看到的教程都是集群版&#xff0c;现实是只有1台机器&#xff0c;故此都是使用这台机器安装。 1.下载对应hadoop安装包 https://dlcdn.apache.org/h…

linux centos7.9改dns和ip

vi /etc/sysconfig/network-scripts/ifcfg-ens32 &#xff1a;wq后 重启网络服务 systemctl restart network —————————————————————————— 篇外话题 软件下载 xshell可以从腾讯软件中心下载

dpdk协议栈之udp架构优化

dpdk优势 传统网络架构与 DPDK&#xff08;Data Plane Development Kit&#xff09;网络架构之间存在许多区别&#xff0c;而 DPDK 的优势主要体现在以下几个方面&#xff1a; 数据包处理性能&#xff1a;传统网络架构中&#xff0c;网络数据包的处理通常由操作系统的网络协议…

探索便捷办公新选择:ONLYOFFICE 桌面编辑器

目录 引言 1. ONLYOFFICE 桌面编辑器简介 2. 功能特点 2.1 多格式支持 2.2 实时协作编辑 2.3 兼容性与格式保持 2.4 丰富的编辑功能 3. 使用方法 3.1 下载安装 3.2 打开文档 3.3 编辑文档 3.4 保存和共享 4. 注意事项 4.1 版本更新 4.2 网络连接 4.3 安全性 5.…

【电子书】移动开发

整理了一些互联网电子书&#xff0c;推荐给大家 移动开发 Android App开发入门与项目实战.epubAndroid Studio应用开发实战详解.epubAndroid Studio开发实战&#xff1a;从零基础到App上线.epubAndroid 游戏开发大全&#xff08;第二版&#xff09;.epubAndroid 源码设计模式…