首页 > 其他分享 >C语言——函数基本知识(三)

C语言——函数基本知识(三)

时间:2024-11-12 22:19:18浏览次数:3  
标签:函数 递归 int 基本知识 C语言 CSDN result 阶乘

        上篇文章我们介绍了函数递归的使用,接下来我们再来讲解一些有关递归的习题。

一. 求n的阶乘

        阶乘是指:n*(n-1)*(n-2)*······*2*1。

        首先我们可以先利用循环实现上面的代码。

代码如下:

​
int main()
{
	int n=0;
	int a;
	int j=1;
	scanf("%d", &n);
	for (a = 1; a <= n; a++)
	{
		j *= a;
	}
	printf("%d", j);

	return 0;
}

​

        这是求阶乘比较简单的代码,但是当我们输入各种数据的时候,我们发现当输入20的时候,结果就不对了,

        出现错误原因很简单,这种叫做阶乘溢出,因为阶乘 j 的类型是int型,而20的阶乘超过了int类型所存储的最大范围,导致阶乘溢出。

        我们可以将上面的代码进行优化。

优化代码如下:

int main()
{
	int n=0;
	int a;
	long long j=1;
	scanf("%d", &n);
	for (a = 1; a <= n; a++)
	{
		j *= a;
	}
	printf("%lld", j);

	return 0;
}

将 j 的类型变成长整型,可以避免阶乘溢出,注意当用printf的时候用“%lld”

接下来我们用函数递归实现n的阶乘。

递归代码如下:

int fac(int x)
{
	if (x >= 1)
	{
		x *= fac(x - 1);
	}
	else
		return 1;
}
int main()
{
	int n;
	scanf("%d", &n);
	int a = fac(n);
	printf("%d", a); 
	return 0;
}

运行结果如下:

二. 求第n个斐波那契数

        斐波那契数列(Fibonacci sequence),又称黄金分割数列 [1],因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称“兔子数列”,其数值为:1、1、2、3、5、8、13、21、34……在数学上,这一数列以如下递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)

普通代码如下:

int fib(int x)
{
	if (x <=2)
		return 1;
	else
		return x = fib(x - 1) + fib(x - 2);
}
int main()
{
	int a;
	scanf("%d", &a);
	int f = fib(a);
	printf("%d", f);
}

但是我们发现有问题:

        在使用 fib 这个函数的时候如果我们要计算第50个斐波那契数字的时候特别耗费时间。 使用 factorial 函数求10000的阶乘(不考虑结果的正确性),程序会崩溃。

        为什么呢?

        我们发现 fib 函数在调用的过程中很多计算其实在一直重复。

        那么如何改进呢???

        1. 将递归改写成非递归。

        2. 使用static对象替代 nonstatic 局部对象。在递归函数设计中,可以使用 static 对象替代 nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放 nonstatic 对象的开销,而且 static 对象还可以保 存递归调用的中间状态,并且可为 各个调用层所访问。  

        比如,下面代码就采用了非递归的方式

优化代码如下:

int fib(int n)
{
	int result;
	int pre_result;
	int next_older_result;
	result = pre_result = 1;
		while (n > 2)
		{
			n -= 1;
			next_older_result = pre_result;
			pre_result = result;
			//将result值给前一个pre_result,把pre_result的值赋给result前面第二个next_older_result
			result = pre_result + next_older_result;
		}
	return result;
}
int main()
{
	int a;
	scanf("%d", &a);
	int f = fib(a);
	printf("%d", f);
}

        提示:

         1. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。

         2. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。

        3. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。

        本节函数基本知识(三)就介绍到这里,之后会更新《函数栈帧的创建与销毁》《函数递归经典题型——汉诺塔问题》《函数递归经典题型——青蛙跳台问题》。

        往期回顾:

C语言 ——函数基本知识(一)-CSDN博客

C语言——函数基本知识(二)-CSDN博客

“山林不向四季起誓,荣枯随缘”——C语言(爱心+祝福语)代码分享_爱心代码朋友圈文案-CSDN博客

C语言——二分法查找讲解_c语言二分法查找一个数-CSDN博客

C语言穷举法算法经典题型(一)_c语言穷举法经典例题-CSDN博客

C语言穷举法算法经典题型(二)_百钱百鸡问题c语言-CSDN博客

C语言算法经典基础题型——求一个数的回文数(两种方法)-CSDN博客

C语言基础入门(小白)三种方法解决幽灵换行符问题-CSDN博客

标签:函数,递归,int,基本知识,C语言,CSDN,result,阶乘
From: https://blog.csdn.net/hjx1235/article/details/143626565

相关文章

  • 字符串搜索一把梭,hook libc.so系统库函数
    在安卓逆向过程,常常遇见一些加密字段没有写在java层,写在native层通过加密算法动态生成,但是只要是一个正常算法的生成,就一定会调用系统的库函数,故写了一段hook系统库函数的代码用于分析加密字符串的生成......
  • C~动态内存函数介绍
    前面咱们与小伙伴们分享了C~库函数的相关知识,今天咱们再介绍一下动态内存函数~一.什么是动态内存函数动态内存函数是指在C语言中用于在程序运行时动态分配和释放内存的一系列标准库函数。这些函数定义在<stdlib.h>头文件中,主要包括malloc、calloc、realloc和free,它们......
  • 一觉睡醒,全世界计算机水平下降100倍,而我却精通C语言——变量
    大家好啊,我是小象٩(๑òωó๑)۶我的博客:XiaoFeiXiangζั͡ޓއއ很高兴见到大家,希望能够和大家一起交流学习,共同进步。*这一节我们来学习变量相关的知识,学习变量的创建和分类,学习并熟悉算术操作符,赋值操作符,单双目操作符的使用,并了解强制类型转换文章目录......
  • 用函数实现模块化程序设计三
    函数的嵌套调用C语言的函数定义是互相平行的、独立的,也就是说,在定义函数时,一个函数内不能再定义另一个函数,也就是不能嵌套定义,但是可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数如上执行过程:执行main函数遇到函数调用的语句,调用函数a,流程转到a函数......
  • Scratch自制积木(自定义函数)求最小公倍数
    在Scratch编程环境中,自制积木是一种用户定义的代码块,它可以将复杂的脚本简化为更易于理解和管理的部分。通过自制积木,用户可以将一系列指令封装成一个单独的积木块,从而方便地在不同的项目中重用这些指令。Scratch自制积木功能是一个强大且灵活的工具,它可以帮助用户更好地组织......
  • C语言进阶 之 数据的存储核心知识点笔记
    1.类型的基本归类(1).整型家族charunsignedcharsignedcharshortunsignedshort[int]signedshort[int]intunsignedintsignedintlongunsignedlong[int]signedlong[int](2).浮点型家族floatdouble(3).构造型家族数组类型结构体类型stru......
  • Java常用方法:StringUtils.isNotBlank()、StringUtils.isEmpty()、去除空格的函数、手
    Java常用方法:StringUtils.isNotBlank()、StringUtils.isEmpty()、去除空格的函数、手机号中间4位换成*、判断字符是否为数字要使用工具类StringUtils,首先得导入依赖<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><ve......
  • c语言解决韩信点兵问题
    原题是这样的:韩信有一队兵,他想知道有多少人,便让士兵排队报数:按从1至5报数,最末一个士兵报的数为1;按从1至6报数,最末一个士兵报的数为5;按从1至7报数,最末一个士兵报的数为4;最后再按从1至11报数,最末一个士兵报的数为10。编程求韩信至少有多少兵?我们通过通过数学方法来理解和解决这......
  • 深⼊理解指针(5)[回调函数、qsort相关知识(qsort可用于各种类型变量的排序)】
     目录1.回调函数2.qsort相关知识(qsort可用于各种类型变量的排序)一   回调函数    1定义/作用:把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅......
  • C语言第九周课——经典算法
    目录一、冒泡法排序1.1原理1.2代码实现(以升序排序为例) 1.3逻辑 1.4分析二、二分法查找2.1原理2.2代码实现 2.3逻辑2.4算法效率分析三、素数判断3.1原理3.2代码实现3.3逻辑3.4分析一、冒泡法排序1.1原理冒泡排序(BubbleSort)是一种简单的排序算法。它重......