C语言第入门——第十六课

目录

一、分治策略与递归

二、递归

1.求解n的阶乘

2.输入整数、倒序输出

3.输入整数、正序输出 

4.计算第n位Fibonacci数列

​编辑5.无序整数数组打印

6.找到对应数组下标 


一、分治策略与递归

在我们遇到大问题的时候,我们的正确做法是将它分解成小问题,然后一个小问题一个小问题解决,这样的策略就是分治策略。

递归是分治策略的一种方式,可以不断地通过自己调用自己来将问题规模逐渐缩小,从而解决问题。

分治策略的特征:

①大规模问题化成小规模问题容易被解决掉

②大规模问题能够被划分为多个相同的小规模问题

③这些小规模问题的解组合起来是大问题的解

④小规模问题是相互独立的

举个例子:

皇帝让你数10个谷仓的米粒,问题规模太大,你可以找100个工人,每人分上相同重量的米进行数,每个人的数量相加就是最终米粒的数量。

这就是一个典型的分治策略问题,将大规模转化为小规模问题,而且是满足上面分治策略的四条特征的。

分治策略不光在我们算法中需要使用,我希望转化成我们的思维模式,帮助我们更好的解决生活中的问题。

二、递归

递归包含两个过程:递推和回归,递推逐层调用,直到递推终止条件满足,再逐层回归。

递归和普通函数调用类似,需要开辟栈帧空间,它只有满足中止条件逐层回归的时候,上一层的函数的栈帧空间才会被释放。注意,不存在无限递归的函数,因为栈帧空间是有限的,所以不能无限调用函数,开辟空间。

递归分为直接递归和间接递归。

直接递归:在函数执行的时候调用函数自身。

间接递归:在函数执行过程中调用其他函数,再调用函数自身。

一般不推荐使用间接递归,因为很容易递推错误。

1.求解n的阶乘

代码如下:

int fabi(int n)
{
	if (n == 1) return 1;
	int sum = fabi(n-1)*n;
	return sum;
}

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

分析:我们将代码复制多份便于观看,但其实只有一个代码哦。

我们这里取n=4,第一次进入到fabi()函数中,n!=1,执行下一条语句fabi(n-1)*n,也就是fabi(3)*4。

然后我们再次调用函数fabi(),此时n=3,我们进入到函数体中n!=1,执行下一条语句fabi(2)*3。

此时我们再次调用fabi()函数,此时n=2,n!=1,执行fabi(1)*2。

这里再次调用fabi()函数,此时n==1,所以我们return 1。

返回到上一层,我们继续执行,此时这条语句为sum = 1*2,我们返回1*2,然后我们继续回归上一层函数,sum = 3*2*1,然后我们再回归,最后得到sum =4*3*2*1,回归结束。

下面第一张是我画的示意图,如果看不清楚再看下面第二张老师画的图,老师画的比较清晰。

红色的线代表递推过程,绿色的线代表回归过程。

 下面解释一下栈帧的动态变化情况。

在每次递推调用函数的时候,程序开辟栈帧空间,在回归的时候再一层层释放掉。

2.输入整数、倒序输出

输入一个整数(无符号整型),使用递归算法将整数倒序输出。

void Show(unsigned int n)
{
	if (n == 0) return ;
	else
	{
		printf("%d", n % 10);
		Show(n / 10);
	}
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	Show(n);
}

逻辑图如下,变量和函数定义不太一样,但是逻辑一致。

3.输入整数、正序输出 

法一:数组法

void Show(unsigned int n)
{	
	int ar[10] = {0};
	int i = 0;
	while (n!=0)
	{
		ar[i] = n % 10;
		n = n / 10;
		i++;
	}
	i--;
	while (i>=0)
	{
		printf("%d ", ar[i]);
		i--;
	}
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	Show(n);
}

法二:递归法

void Show(unsigned int n)
{
	if (n == 0) return;
	else
	{
		Show(n / 10);
		printf("%d", n % 10);

	}
}
int main()
{
	unsigned int n = 0;
	scanf("%d", &n);
	Show(n);
}

4.计算第n位Fibonacci数列

法一:循环输出

int Fibonna(int n)
{
	int a = 1;
	int b = 1;
    if (n==0) return 0;
	if (n == 1 || n == 2)
	{
		return 1;
	}
	else
	{
		int i = 0;
		int temp = 0;
		int result = 0;
		while (i<n-2)
		{
			result = a + b;
			temp = b;
			b = result;
			a = temp;
			i++;
		}
		return result;
	}

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

法二:递归输出

int Fibonna(int n)
{
    if (n == 0) return 0;
	if (n == 1|| n == 2)
	{
		return 1;
	}
	else
	{
		return (Fibonna(n - 1) + Fibonna(n - 2));
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int result =Fibonna(n);
	printf("%d",result);
}

Q: 使用递归进行输出的时候空间复杂度是2^n,很大,怎么样降低时间复杂度?

A: 想要降低复杂度,主要就是要减少一个递归函数,将递归过程中的值存储下来就能减少相应的复杂程度。

写法一:一定要注意a,b,temp不能每次被调用的时候都初始化,要不然输出的值不正确。

int fac(int n)
{
	static int a = 1;
	static int b = 1;
	static int temp = 1;
	if (n <= 2) return temp;
	temp = a + b;
	b = a;
	a = temp;
	fac(n - 1);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int result = fac(n);
	printf("%d", result);
}

写法二:思路一致,只不过老师写的更清楚明了。

int fanc(int n, int a, int b)
{
	if (n <= 2) return a;
	else return fanc(n - 1, a + b, a);
}
int fac(int n)
{
	int a = 1;
	int b = 1;
	return fanc(n, a, b);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int result = fac(n);
	printf("%d", result);
}

5.无序整数数组打印

有一个整型数组,数值无序,使用循环和递归打印和查询。

法一:循环打印

void Show_Arr(const int* ar, const int  n)
{
	if (n < 1 || ar == NULL) return;
	for (int i = 0; i < n; i++)
	{
		printf("%d ", ar[i]);
	}
}
int main()
{
	const int n = 3;
	int ar[n] = { 12,23,34 };
	Show_Arr(ar,n);
}

法二:使用递归打印数组

void Show_Arr(const int* ar, const int  n)
{
	if (n < 1 || ar == NULL) return;
	Show_Arr(ar, n - 1);
	printf("%d ", ar[n - 1]);

}
int main()
{
	const int n = 3;
	int ar[n] = { 12,23,34 };
	Show_Arr(ar, n);
}

Q:上述递归代码我可可以将n-1修改成n--吗?请详细说明。

A:不可以修改,后置--是先取值后--,在下面示例中,n=3,n>0,调用函数,调用的新的函数还是n=3的函数,进入到一个循环,直到栈帧空间被填满。

Q:上述递归代码我可可以将n-1修改成--n吗?请详细说明。

A:也不可以修改,前置--是先--再取值,的确可以满足递归调用的逻辑,但是当他进行回归的时候会n的值被更改了,输出的是更改后的n-1,造成数据溢出问题。

6.找到对应数组下标 

法一:循环找数组下标

int FindValue(const int* arr, int n, int value)
{
	if (n < 1 || arr == NULL)	return 0;
	int pos = -1;
	for (int i = 0; i < n; i++)
	{
		if (arr[i] == value)
		{
			pos = i;
			break;
		}
	}
	return pos;
}
int main()
{
	const int n = 5;
	int arr[n] = { 10,11,12,13,14 };
	int val = 0;
	scanf("%d", &val);
	int m = FindValue(arr, n, val);
	printf("%d", m);
}

法二:递归找数组下标

这面这个代码输出的数组下标有问题,一直是-1

int FindValue(const int* br, int n, int val)
{
	int pos = -1;
	if (NULL == br || n < 1) return pos;
	if (br[n-1] == val)
	{
		pos = n - 1;
	}
	else
	{
		FindValue(br, n - 1, val);
	}
	return pos;
}
int main()
{
	const int n = 5;
	int arr[n] = { 10,11,12,13,14 };
	int val = 0;
	scanf("%d", &val);
	int m=FindValue(arr,n,val);
	printf("%d", m);
}

正确代码 

int FindValue(const int* br, int n, int val)
{
	int pos = -1;
	if (NULL == br || n < 1) return pos;
	if (br[n-1] == val)
	{
		pos = n - 1;
	}
	else
	{
		pos =FindValue(br, n - 1, val);
	}
	return pos;
}
int main()
{
	const int n = 5;
	int arr[n] = { 10,11,12,13,14 };
	int val = 0;
	scanf("%d", &val);
	int m=FindValue(arr,n,val);
	printf("%d", m);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实验六:Android的网络编程基础

实验六&#xff1a;Android 的网络编程基础 6.1 实验目的 本次实验的目的是让大家熟悉 Android 开发中的如何获取天气预报&#xff0c;包括了 解和熟悉 WebView、WebService 使用、网络编程事件处理等内容。 6.2 实验要求 熟悉和掌握 WebView 使用 了解 Android 的网络编程…

Unity 预制体放在场景中可见,通过代码复制出来不可见的处理

首先我制作了一个预制体&#xff0c;在场景中是可见的&#xff0c;如下图 无论是Scene视图&#xff0c;还是Game视图都正常。 我把预制体放到Resources里面&#xff0c;然后我通过如下代码复制到同个父物体下。 GameObject obj1 Instantiate(Resources.Load("Butcon&quo…

windows使用lcx端口转发登陆远程主机

1.编译lcx源码: GitHub - UndefinedIdentifier/LCX: 自修改免杀lcx端口转发工具 2.在win7上安装vs2010并编译生成lcx.exe 3.在要被控制主机上运行: lcx -slave 192.168.31.248 51 192.168.31.211 3389 192.168.31.248为远程主控制主机,51为远程主机端口 192.168.31.211为被…

Web server failed to start. Port 8080 was already in use.

Windows 服务端口被占用&#xff0c;杀死进程命令&#xff1a; netstat -ano | findstr 8080taskkill -PID [xxx] -F

9款AI让你在2分钟内创建任何东西

1、免费AI绘画&#xff1a;LeonardoAi一个免费的 Midjourney 替代品&#xff0c;能够快速创建高品质和风格统一的视觉图片&#xff0c;帮你释放创造力。 2、 模板编辑AI&#xff1a;Canva 将所有AI的强大功能汇聚于一处&#xff0c;为你的工作流程注入超级动力。 3、构建网站&…

【C++初阶】STL详解(二)string类的模拟实现

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

07 robotframework JS和RFS值传递

1、JS的值传给RFS变量 示例1&#xff1a; ${bb} Execute Javascript function rand ( n ){return ( Math.floor ( Math.random ( ) * n 1 ) );};var aa rand(100);return aa; sleep ${bb}ms 示例2&#xff1a; var a [];$("iframe&quo…

UE4动作游戏实例RPG Action解析一:角色移动,旋转,动画创建,创建武器,及武器配置

文末有git地址 一、角色移动,摄像机旋转 1.1、官方RPGAction Demo下载地址: ​ 1.2、在场景中创建一个空的角色 创建一个Character蓝图和一个PlayerController蓝图,添加弹簧臂组件和摄像机,并为网格体添加上一个骨骼网格体 ​ 1.3、如何让这个角色出现在场景中, 创建一…

前端性能优化的方式

文章目录 前言DNS 预解析存储使用 HTTP / 2.0预加载预渲染懒执行与懒加载文件优化webpack优化如何根据chrome的timing优化移动端优化后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;前端系列文章 &#x1f431;‍&#x1f453;博主在前端…

Kafka入门教程与详解(一)

Kafka入门教程与详解&#xff08;一&#xff09; 一、Kafka入门教程 1.1 消息队列&#xff08;Message Queue) Message Queue消息传送系统提供传送服务。消息传送依赖于大量支持组件&#xff0c;这些组件负责处理连接服务、消息的路由和传送、持久性、安全性以及日志记录。消…

鞋业生产制造用什么ERP软件?能为企业带来哪些好处

鞋服这类商品的种类众多&#xff0c;同时也是我们生活当中较为常见的产品&#xff0c;各个制鞋企业有差异化的营销渠道和经营模式&#xff0c;日常生产过程存在的问题呈现多样化。 有些制鞋企业依然采用传统的管理方式&#xff0c;在这种模式之下&#xff0c;企业并不能随时掌…

西浦成立产业家学院破解 “产业级” 问题!AMT企源成首批合作机构

在推动高质量发展的国家战略背景下&#xff0c;从集成电路到人工智能&#xff0c;从新能源到绿色低碳&#xff0c;从健康养老到数字文创&#xff0c;无论国家还是区域都面临着产业转型升级或突破创新的发展需求&#xff0c; 这些 “产业级” 问题的难度远非单个企业层面问题可比…

微信小程序 限制字数文本域框组件封装

微信小程序 限制字数文本域框 介绍&#xff1a;展示类组件 导入 在app.json或index.json中引入组件 "usingComponents": {"text-field":"/pages/components/text-field/index"}代码使用 <text-field maxlength"500" bindtabsIt…

思源笔记的优缺点 vs Obsidian vs Logseq vs Trilium

新用户对思源笔记的印象。&#xff08;PS&#xff1a;两年前我试用过思源笔记&#xff0c;被卡顿劝退了&#xff09; 优点 相比obsidian&#xff0c; 可在文档树拖拽 拖拽调整笔记顺序 拖拽使一个笔记成为另一个笔记的子笔记&#xff0c;树状结构 设置-文档树&#xff0c;默认…

鸿蒙APP外包开发需要注意的问题

在进行鸿蒙&#xff08;HarmonyOS&#xff09;应用开发时&#xff0c;开发者需要注意一些重要的问题&#xff0c;以确保应用的质量、性能和用户体验。以下是一些鸿蒙APP开发中需要特别关注的问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软…

Linux 基础操作手记四

文章目录 环境变量生效配置python版本安装SSH关闭GUIvi 清空 环境变量生效 source ~/.bashrc # 或 source ~/.zshrc 配置python版本 sudo add-apt-repository ppa:deadsnakes/ppa sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 sudo upd…

C++初阶:STL之string类

一.为什么学习string类&#xff1f; 在C语言中没有字符串这一数据类型&#xff0c;都是用字符数组来处理字符串&#xff0c;C也支持这种C风格的字符串。除此之外&#xff0c;C还提供了一种自定义数据类型--string&#xff0c;string是C标准模板库(STL)中的一个字符串类&#x…

React项目首页中用canvas实现星空

文章目录 前言代码使用后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;前端系列文章 &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出现错误&#xff0c;感谢大家…

2019年全国硕士研究生入学统一考试管理类专业学位联考数学试题——解析版

2019 年 1 月份管综初数真题 一、问题求解&#xff08;本大题共 5 小题&#xff0c;每小题 3 分&#xff0c;共 45 分&#xff09;下列每题给出 5 个选项中&#xff0c;只有一个是符合要求的&#xff0c;请在答题卡上将所选择的字母涂黑。 1、某车间计划 10 天完成一项任务&a…

springboot集成xxl-job详解

文章目录 springboot集成xxl-job详解1、springboot集成xxl-job&#xff1a;&#xff08;1&#xff09;pom文件里引入xxl-job依赖&#xff08;2&#xff09;application.properties配置文件&#xff1a;&#xff08;3&#xff09;在你的项目里新建文件结构如下&#xff1a;XxlJo…