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

news2024/11/18 1:46:00

目录

一、分治策略与递归

二、递归

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);
}

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

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

相关文章

3DMAX平铺插件MaxTiles教程

MaxTiles 结合了一组材质和地图插件&#xff0c;任何建筑师或 3D 可视化艺术家都会喜欢。与静态位图纹理不同&#xff0c;MaxTiles 材质可以更改键合图案、替换和混合砖块、更改边缘、随机化颜色、位置、表面等等。MaxTiles 结合了以下功能&#xff1a; 墙壁和瓷砖 – 用于创建…

【计算思维】蓝桥杯STEMA 科技素养考试真题及解析 5

1、要把下面4张图片重新排列成蜗牛的画像&#xff0c;该如何排列这些图片 A、 B、 C、 D、 答案&#xff1a;A 2、将下图的绳子沿虚线剪开后&#xff0c;绳子被分成了()部分 A、6 B、7 C、8 D、9 答案&#xff1a;C 3、下面的立体图形&#xff0c;沿箭头方向看去&#…

“世亚智博会,世亚软博会”双展联动,3月上海,4月杭州,6月北京

2024世亚智博会与世亚软博会双展联动&#xff0c;3月上海&#xff0c;4月杭州&#xff0c;6月北京&#xff0c;历经多年沉淀与打磨&#xff0c;随着扩张速度的不断加快&#xff0c;参展企业的数量也水涨船高&#xff0c;引领行业前沿趋势&#xff0c;已成为智能产业和软件行业的…

【uniapp】Google Maps

话不多说 直接上干货 提前申请谷歌地图账号一、新建地图 使用h5获取当前定位或者使用三方uniapp插件 var coords ""navigator.geolocation.getCurrentPosition(function(position) {coords {lat: position.coords.latitude,lng: position.coords.longitude};lats …

windows安装wsl2以及ubuntu

查看自己系统的版本 必须运行 Windows 10 版本 2004 及更高版本&#xff08;内部版本 19041 及更高版本&#xff09;或 Windows 11 才能使用以下命令 在设置&#xff0c;系统里面就能看到 开启windows功能 直接winQ搜 开启hyber-V、使用于Linux的Windows子系统、虚拟机平…

让资产权利归于建设者:Kiosk使过程变得更简单

区块链凭借着其将人的权利地位置于平台之上的能力&#xff0c;可以重塑互联网&#xff0c;而自托管为个人提供了控制和管理其资产和数据的能力。链上交易支持建设者和客户之间的点对点交易。这些特质联合起来&#xff0c;可以将数字世界从基于价值提取的模式转变为基于价值创造…

机器学习第7天:逻辑回归

文章目录 介绍 概率计算 逻辑回归的损失函数 单个实例的成本函数 整个训练集的成本函数 鸢尾花数据集上的逻辑回归 Softmax回归 Softmax回归数学公式 Softmax回归损失函数 调用代码 参数说明 结语 介绍 作用&#xff1a;使用回归算法进行分类任务 思想&#xff1a;…

MATLAB 模型预测控制(MPC)控制入门 —— 设计并仿真 MPC 控制器

系列文章目录 文章目录 系列文章目录前言一、使用 MPC Designer 设计控制器1.1 CSTR 模型1.2 导入被控对象并定义 MPC 结构1.3 定义输入和输出通道属性1.4 配置仿真场景1.5 配置控制器水平线1.6 定义输入约束条件1.7 指定控制器调整权重1.8 消除输出超调1.9 测试控制器抗干扰能…

15项基本SCADA技术技能

1. 人机界面 人机界面是将操作员连接到设备、系统或机器的仪表板或用户界面。 以下是 hmi 在 scada 技术人员简历中的使用方式&#xff1a; 完成了查尔斯湖废水处理厂和提升站的完整 HMI 图形界面。对加油系统、加油车、PLC、HMI、触摸屏进行故障排除和维修。对 Horner HMI …

吴恩达《机器学习》8-7:多元分类

在机器学习领域&#xff0c;经常会遇到不止两个类别的分类问题。这时&#xff0c;需要使用多类分类技术。本文将深入探讨多类分类&#xff0c;并结合学习内容中的示例&#xff0c;了解神经网络在解决这类问题时的应用。 一、理解多类分类 多类分类问题是指当目标有多个类别时…

homeassiant主题

下载主题 https://github.com/maartenpaauw/home-assistant-community-themes.git 使用file editor到homeassiant路径下&#xff0c;新建文件夹themes文件夹&#xff0c;用terminal新建也可以。 使用file editor上传文件 使用Terminal解压 mkdir themes unzip home-assistan…

达芬奇DaVinci Resolve Studio 18.6.3 for Mac

DaVinci Resolve Studio 18是一款专业的视频编辑和调色软件&#xff0c;适用于电影、电视节目、广告等各种视觉媒体的制作。它具有完整的后期制作功能&#xff0c;包括剪辑、调色、特效、音频处理等。 以下是DaVinci Resolve Studio 18的主要特点&#xff1a; - 提供了全面的视…

IDEA中安装Docker插件实现远程访问Docker

开启远程Docker访问 #修改Docker服务文件&#xff0c;需要先切换到root用户 vim /lib/systemd/system/docker.service #注释掉"ExecStart"这一行&#xff0c;并添加下面这一行信息 ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock…

【SpringBoot】 环境准备

一.SpringBoot准备 1.下载idea 社区版 2021.1 - 2022.1.4 专业版 无要求 2.Maven 是一个工具,和Java没有关系 . 主要功能是项目构建和依赖管理. 项目构建 上述对应的都是maven命令 . 依赖管理 添加坐标之后,点击刷新,右侧就会载入依赖. Maven还有依赖传递和依赖排除功…

Simulink 自动代码生成电机控制:模型预测控制(MPC)模块使用总结(1)

目录 前言 MPC模块使用步骤和参数设计 电机控制系统验证 MPC参数调整 MPC和PI控制器比较 总结 前言 前面尝试了基于电机DQ轴电流环的传递函数设计PI控制器的参数&#xff0c;最近尝试了下模型预测控制&#xff08;MPC&#xff09;对电流环进行控制&#xff0c;这里总结一下…

智能井盖传感器能不能监测井盖位移

智能井盖传感器能够精准监测井盖的位移。这些传感器运用了前沿科技对井盖状态进行实时监测。一旦井盖出现异常移动传感器会立即捕捉到信号&#xff0c;并通过与互联网相连接的智能系统发出警报或记录数据。这种智能监测仪为城市或相关部门的井盖管理提供了实时数据支持&#xf…

Acer宏碁Predator掠夺者笔记本PH315-51原装出厂Windows10系统工厂模式ISO镜像文件

下载链接&#xff1a;https://pan.baidu.com/s/1GGRKYLQzl6SxdtCXbnzhrA?pwdrel7 提取码&#xff1a;rel7 宏基原厂Win10系统自带重置功能、带所有驱动、PredatorSense风扇键盘控制中心、Office办公软件、出厂主题壁纸、系统属性Acer宏基专属的LOGO标志、 Acer Care Center…

C#,数值计算——插值和外推,双线性插值(Bilin_interp)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// 双线性插值 /// interpolation routines for two dimensions /// Object for bilinear interpolation on a matrix. /// Construct with a vector of x1. /// value…

Vue3-watchEffect函数

Vue3-watchEffect函数 功能&#xff1a;watchEffect 函数在一开始时就会执行一次&#xff0c;而当中的回调函数的属性发生变化&#xff0c;那么watchEffect 就会再执行一次&#xff0c;主要作用还是在于监视回调函数每次的变化。 // App.vue <template><h2>计数…

Idea 创建 Spring 项目(保姆级)

描述信息 最近卷起来&#xff0c;系统学习Spring&#xff1b;俗话说&#xff1a;万事开头难&#xff1b;创建一个Spring项目在网上找了好久没有找到好的方式&#xff1b;摸索了半天产出如下文档。 在 Idea 中新建项目 填写信息如下 生成项目目录结构 pom添加依赖 <depende…