【C语言】递归实战,通过几个例子带你深入走进递归算法

news2024/11/26 0:43:13

在这里插入图片描述

君兮_的个人主页

勤时当勉励 岁月不待人

C/C++ 游戏开发


Hello,这里是君兮_,今天给大家带来一篇递归的实战教学文章,由于递归算法不仅对于初学者十分不易理解并且在我们以后的数据结构中也非常重要。我们今天就通过几个应用递归的实际例子来给大家彻底讲透递归算法!

  • 废话不多说咱们直接开始吧!!

递归实战详解

  • 一.什么是递归?
  • 实战一. 打印整型数据的每一位
      • 画图解释分析
      • 循环实现
  • 实战二.汉诺塔问题
    • 什么是汉诺塔?
    • 思路分析:
  • 实战三.青蛙跳台阶问题
    • 青蛙跳台阶问题的描述
    • 青蛙跳台阶问题解题思路分析
      • 思路总结
  • 总结

一.什么是递归?

  • 程序调用自身的编程技巧称为递归( recursion)。
  • 递归做为一种算法在程序设计语言中广泛应用。 递归算法通常指一个过程或函数在其定义或说明中直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
  • 递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。(也就是说我们现在学的需要使用递归的场景大多数通过循环也能解决,在下面介绍的例子中会用循环也实现一遍)
  • 递归的主要思考方式在于:把大事化小
  • 当你在使用递归时遇到思考瓶颈,请牢记大事化小的思想!!
  • 具体有关递归知识的详解请看以下链接,这里我们是结合实战例子讲,就不在此具体展开了。
    【C语言】带你玩转递归,迭代算法

实战一. 打印整型数据的每一位

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

例如:
输入:1234,输出 1 2 3 4

代码如下:

#include <stdio.h>
void print(int n)
{
if(n>9)//如果不大于9直接打印当前n的值即可
{
print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}
  • 我们想要把一个四位数甚至更多位的数每一位给剥离出来,首先要想到的是怎么得到每一位
  • 我们知道,对10取余%就可以得到这个数的个位的数,而除以10就可以把这一位给消去,此时我们就可以这样实现(以下把n当作一个四位数举例)
  • 先让n对10%得到此时这一位的数,然后将n/10来到下一位,再让n对10%得到这位数继续朝下进行直至n对10%等于0,说明此时n是个小于10的数只剩下它需要取了,取下它结束递归即可

画图解释分析

  • 递归的递就是传递的意思,而归的意思是回归
    在这里插入图片描述
    这就是递归!
  • 解释完了递归在这段代码的应用,我们来讲讲这个代码中出现的问题
  • 当我们中用户某天突发奇想输入了一个负数进去会发生什么呢?
    在这里插入图片描述
  • 我们这个程序设定的条件是只针对正数的,要想输入一个负数也能打印就得这样修改代码
void print(int n)
{
	if (n > 9)//如果不大于9直接打印当前n的值即可
	{
		print(n / 10);
	}
	else if (n < -9)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	int num = -1234;
	print(num);
	return 0;
}

或者把我们传入的int改为一个无符号整型

void print(unsigned int n)
{
	if (n > 9)//如果不大于9直接打印当前n的值即可
	{
		print(n / 10);
	}
	/*else if (n < -9)
	{
		print(n / 10);
	}*/
	printf("%d ", n % 10);
}
  • 我在这里想提醒大家的是,无论在递归或者任何其他程序的编写中我们都得尽可能考虑各方面的情况,在以后的程序猿工作中,我们要知道用户是不总是照着你的指示来使用程序的,我们得尽可能保证程序的避免上面这种bug。
  • 递归往往都能通过循环实现,我们现在来把这个例子用循环的方法实现一下

循环实现

//判断输入数字位数
#include<math.h>
int Strlen(unsigned int n)
{
	int count = 0;
	while (n / 10)
	{
		count++;
		n /= 10;
	}
	return count;
}

void print(unsigned int n)
{
	int i = 0;
	int ret = Strlen(n);
	if (n > 9)
	{
		for (i = ret; i > 0; i--)
		{
			int m = pow(10, i);
			printf("%d ", n / m);
			n %= m;
		}
	}
	printf("%d", n);
	
	
}
int main()
{
	int num = 123456789;
	print(num);
	return 0;
}
  • 我们先来看看效果
    在这里插入图片描述

实战二.汉诺塔问题

什么是汉诺塔?

  • 汉诺塔(Tower of Hanoi)源自印度古老传说的一个游戏,大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,并且在移动时三根柱子之间一次只能移动一个圆盘。

  • 从上面的对于汉诺塔问题的说明我们可以得到这样一个结论

  • 如果要把A柱上的盘子全部都移动到C柱上,要遵循以下规则:

  • 1.每次只能移动A柱最上面的一个盘子

  • 2.小盘子上不能放大盘子。

我们来一步一步分析,首先设此时A中有n个盘子,我们现在的目标是借助B柱把A上的盘子全部移动到C柱上

思路分析:

当需要A上需要移动的盘子n=2时
我们只需要先把A最上面的盘子移到B上,再把A另一个盘子移到C上,最后把B上盘子移到C上即可。

当需要A上需要移动的盘子n=3时
将2个盘子从A移动到B上。重复n=2时的步骤,此时是将那2个盘子从A借助C移动到B上
接着,把A上的盘子移动到C上 ,将B上的2个盘子移动到C上。重复n=2时的步骤,此时是将那2个盘子从B借助A移动到C

当需要A上需要移动的盘子n=4时
将3个盘子从A移动到B上。重复n=3时的步骤,与n=3不同之处在于,我们此时是借助C把A上盘子移到B
将A上最后一个盘子移动到C上
将B上的3个盘子移动到C上。重复n=3时的步骤,与n=3不同之处在于,我们此时是借助A把B上盘子移到C

当需要A上需要移动的盘子为n时
怎么样,经过上面的讲解你发现规律了吗?
也就是说,对于任意一个大于1的正整数n,如果有一个n层汉诺塔的问题,我们就可以将之分解为两个n-1层汉诺塔问题求解

  • 通过我们上面的分析,我们就可以把这个问题的解决分成这三步:

  • 1.将A上n-1层的盘子通过C移动到B上

  • 2.将此时A上剩余的盘子移动到C上

  • 3.将B上此时n-1层的盘子通过A移动到C上

  • 参考代码如下:

#include<stdio.h>

void Move (char A, char C, int n)
{
	printf("把第%d个盘子从%c--->%c\n", n, A, C);
}

void HanoiTower(char A, char B, char C, int n)
{
	if (n == 1)
	{
		Move(A, C, n);
	}
	else
	{
		//将n-1个盘子从A柱借助于C柱移动到B柱上
		HanoiTower(A, C, B, n - 1);
		//将A柱最后一个盘子移动到C柱上
		Move(A, C, n);
		//将n-1个盘子从B柱借助于A柱移动到C柱上
		HanoiTower(B, A, C, n - 1);
	}
}

int main()
{
	int n = 0;
	printf("输入A柱子上的盘子个数:");
	scanf("%d", &n);
	//将n个盘子从A柱借助于B柱移动到C柱上
	HanoiTower('A', 'B', 'C', n);
	return 0;
}

在这里插入图片描述


实战三.青蛙跳台阶问题

青蛙跳台阶问题的描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多上种跳法。


青蛙跳台阶问题解题思路分析

  • 当N=1时,那么青蛙就只有一种跳法。

  • 当N=2时,青蛙可以跳两次一层台阶也可以跳一次二层台阶,有两种跳法。

  • 当N=3时,青蛙可以先跳一次一层台阶,那么还需要跳两层台阶,那它此时就是N=2时的跳法,有两种跳法。
    当青蛙跳一次二层台阶时,此时只需要跳一层台阶,那么它就是N=1时的跳法。
    此时它的跳法就等于(N=1)+(N=2)种跳法。

  • 当N=4时,青蛙跳一次一层台阶时,还需要跳三层台阶,那它此时剩下的跳法就等于N=3时的跳法,即有三种跳法
    青蛙跳一次二层台阶时,还剩二层台阶需要跳,那它此时剩下的跳法就是N=2时的跳法,则有两种跳法。
    那么此时它的跳法就等于(N=2)+(N=3)种跳法。

思路总结

  • 那么,不难看出青蛙跳台阶的规律,当N>2时,此时的跳法数就等于前面两个青蛙跳台阶跳法数之和

  • 青蛙跳台阶代码实现

#include<stdio.h>
int Jump(int n)
{
	if (n == 1)
	{
		return 1;//当只有一层台阶时直接返回1
	}
	 if (n == 2)
	{
		return 2;//当只有2层台阶时就返回2
	}
	 if (n > 2)
	 {
		 return Jump(n - 1) + Jump(n - 2);
	 }//当n>2时,利用递归进行返回
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int num = Jump(n);
	printf("%d\n", num);
	return 0;
}
 
  • 以上的汉诺塔与青蛙跳台阶的思路分析这块由于篇幅原因都是简单的分析了一下,详细的可以看看下面我的这两篇博客:
    【C语言】图文解析,深入浅出汉诺塔问题
    【C语言】手把手带你解决青蛙跳台阶问题

总结

  • 今天的内容暂时到这里就结束了,我们今天通过几个实战例子带大家了解了递归的应用,我希望你如果看懂了能够自己独立的实现一下,这样才叫真正的学会了。

  • 好了,如果你有任何疑问欢迎在评论区或者私信我提出,大家下次再见啦!

新人博主创作不易,如果感觉文章内容对你有所帮助的话不妨三连一下这个新人博主再走呗。你们的支持就是我更新的动力!!!

**(可莉请求你们三连支持一下博主!!!点击下方评论点赞收藏帮帮可莉吧)**

在这里插入图片描述

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

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

相关文章

Apache Doris 在头部票务平台的应用实践:报表开发提速数十倍、毫秒级查询响应

作者&#xff5c;国内某头部票务平台 大数据开发工程师 刘振伟 本文导读&#xff1a; 随着在线平台的发展&#xff0c;票务行业逐渐实现了数字化经营&#xff0c;企业可以通过在线销售、数字营销和数据分析等方式提升运营效率与用户体验。基于此&#xff0c;国内某头部票务平…

【Java】Java核心 81:Git 教程(4)差异比较 版本回退

文章目录 06.GIT本地操作-差异比较目标内容小结 07.GIT本地操作-版本回退目标内容小结 在Git中&#xff0c;可以使用差异比较命令和版本回退命令来查看文件之间的差异并回退到早期的版本。 以下是对这些操作的简要解释&#xff1a; 差异比较&#xff1a;你可以使用git diff命…

本地Linux 部署 Dashy 并远程访问

文章目录 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 转载自cpolar极点云文章&#xff1a;本地Linux 部署 Dashy 并远程访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你…

video-04-videojs配置及使用

videojs是一种轻框架&#xff0c;可以帮我们快速开发一个video视频组件 目录 一、参考资料 二、引入videojs 三、简单了解使用 四、配置项和事件 4.1 常用配置项 4.2 常用事件 4.3 常用方法 4.4 网络状态 4.5 播放状态 4.6 视频控制 五、实例&#xff08;可直接复制…

升级iOS 17测试版后如何降级?iOS17降级教程

对于已经升级到 iOS 17 测试版的用户&#xff0c;如果在体验过程中&#xff0c;感觉到并不是那么稳定&#xff0c;例如出现应用程序不适配、电池续航下降、功能无法正常启用等问题&#xff0c;想要进行降级操作&#xff0c;可以参考本教程。 降级前注意事项&#xff1a; 1.由于…

Android 自定义手写签字板,签署姓名,签名

各位大佬好又来记笔记了~ 今天要做的是签字板&#xff0c;实现客户签名功能&#xff0c;直接看效果&#xff1a; 逐个进行签字&#xff0c;可以避免连笔导致识别不清问题。就是想要客户一个一个写&#xff0c;认真写~~。 下面方框显示的“王某才” 其实是三张图片&#xff0c;…

【算法题】动态规划中级阶段之不同路径、最小路径和

动态规划中级阶段 前言一、不同路径1.1、思路1.2、代码实现 二、不同路径 II2.1、思路2.2、代码实现 三、最小路径和3.1、思路3.3、代码实现 总结 前言 动态规划&#xff08;Dynamic Programming&#xff0c;简称 DP&#xff09;是一种解决多阶段决策过程最优化问题的方法。它…

卸载及安装docker的教程-ubuntu

一、前言 万地高楼平地起~ 二、环境 OS&#xff1a;Ubuntu 20.04 64 bit 显卡&#xff1a;NVidia GTX 2080 Ti CUDA&#xff1a;11.2 三、卸载docker 1、删除docker及安装时自动安装的所有包 apt-get autoremove docker docker-ce docker-engine docker-ce-*for pkg in …

linux -信号量semphore分析

linux -信号量分析 1 struct semaphore和sema_init1.1 struct semaphore1.2 sema_init 2 down3 up4 down_interruptible5 down_killable6 down_timeout7 down_trylock 基于linux-5.15分析&#xff0c;信号量在使用是是基于spin lock封装实现的。 1 struct semaphore和sema_ini…

爬虫入门指南:如何使用正则表达式进行数据提取和处理

文章目录 正则表达式正则表达式中常用的元字符和特殊序列案例 使用正则表达式提取数据案例存储数据到文件或数据库使用SQLite数据库存储数据的示例代码SQLite基本语法创建表格&#xff1a;插入数据&#xff1a;查询数据&#xff1a;更新数据&#xff1a;删除数据&#xff1a;条…

【雕爷学编程】Arduino动手做(137)---MT8870语音解码

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

【uview calendar日历 】如何选择今天之前的数据

在日常工作中&#xff0c;使用uniappuview的ui组件&#xff0c;使用日历组件默认是无法选择当前之前的日期&#xff0c;现在讲下解决的方法 设置 最小的可选日期minDate&#xff0c;最大可选日期maxDate&#xff0c; 默认选中的日期&#xff0c;mode为multiple或range是必须为数…

自定义选项卡组件,选项可插槽html

文件夹xxtabs 四个文件 index暴露 render vue添加虚拟节点到插槽&#xff08;自定义标签结构&#xff09; tabs选项卡整体 abpaneq切换区 tabs.vue <template><div class"gnip-tab"><div class"gnip-tab-nav"><divv-for"(item,…

“sudo”组不存在”或“用户不在 sudoers 文件中。此事将被报告”

解决方法: 使用命令&#xff1a;usermod -a -G sudo tom (换成其他的用户名&#xff0c;也是一个道理)&#xff0c;不过还是不行。 实际解决还是要执行 sudo visudo &#xff0c;在这个文件中去添加用户 这样修改之后&#xff0c;保存并退出&#xff0c;亲测有效&#xff01; …

【FFmpeg实战】AAC编码介绍

AAC&#xff08;Advanced Audio Coding&#xff0c;译为&#xff1a;高级音频编码&#xff09;&#xff0c;是由Fraunhofer IIS、杜比实验室、AT&T、Sony、Nokia等公司共同开发的有损音频编码和文件格式。 对比MP3 AAC被设计为MP3格式的后继产品&#xff0c;通常在相同的比…

训练自己的ChatGPT 语言模型(一).md

0x00 Background 为什么研究这个&#xff1f; ChatGPT在国内外都受到了广泛关注&#xff0c;很多高校、研究机构和企业都计划推出类似的模型。然而&#xff0c;ChatGPT并没有开源&#xff0c;且复现难度非常大&#xff0c;即使到现在&#xff0c;没有任何单位或企业能够完全复…

Atlas200 DK A2与Arduino进行UART串口通信

我们在做一些人工智能的应用开发时往往使用人工智能开发板作为上位机&#xff08;比如我们的小滕&#xff09;&#xff0c;Arduino、stm32等作为下位机控制板&#xff0c;通过上位机进行人工智能模型的推理之后进而给下位机传输对应的控制命令实现智能控制。那么如何实现两者的…

简化交互体验——探索Gradio的ClearButton模块

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

ndarray对象怎样创建?ndarray基本属性列举

numpy中包含一个N维数组对象&#xff0c;即ndarray对象&#xff0c;该对象具有矢量算术能力和复杂的广播能力&#xff0c;常用于科学计算。ndarray对象中的元素可以通过索引访问&#xff0c;索引序号从0开始;ndarray对象中存储的所有元素的类型必须相同。创建ndarray对象的方式…

输入框设置placeholder的文字居中

<input classlogin-form-pwd placeholder请输入商家登录密码 placeholder-class"center"></input> .center{ text-align: center; }