首页 > 其他分享 >函数递归(C语言)(详细过程!)

函数递归(C语言)(详细过程!)

时间:2024-06-10 19:28:50浏览次数:13  
标签:函数 迭代 int 代码 C语言 递归 我们

函数递归

一. 递归是什么

递归是学习C语言很重要的一个知识,递归就是函数自己调用自己,是一种解决问题的方法,下面就使用一个简单的代码帮助大家理解:下面展示一些 内联代码片


#include <stdio.h>
int main()
{
printf("hehe\n");
main()  //出现了main函数自己调用自己
return 0;

在这里插入图片描述
上图展示的代码就是一个简单的调用函数的例子,不断的调用main函数也就是要不断输出hehe,形成了一个循环,这就是一个简单的函数递归。

1.1 递归的思想

把一个大型问题转换成一个与原问题相似但是规模较小的子问题来解决,直到到子问题不能再被拆分,递归就结束了。递归中的递就是递推的意思,归就是回归的意思,下面会有详细的解释。

1.2 递归的限制条件

递归在书写的时候,有两个必要条件:
. 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续
. 每次递归之后越来越接近这个限制条件

二. 递归举例

2.1 求n的阶乘

为了让大家更好理解递归是怎么回事,我们可以举几个例子,下面为大家展示第一个例子求n的阶乘的代码: 内联代码片

int Fact(int n)
{
	if (n == 0)
		return 1;
	else if (n > 0)
		return n * Fact(n - 1);//相当于是多次调用这个函数,形成一个循环,不断地累乘
}

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

上述代码就给大家演示了一遍比较基本的函数递归,我们可以看到如果n大于0的话,就会返回n*Fact(n-1),所以就相当于不断的调用Fact函数,如果大家还是不太理解,下面我们用一张图帮助大家进一步理解:在这里插入图片描述

2.2 按顺序打印一个整数的每一位

这是为大家展示的第二个例子,按顺序打印一个整数的每一位。首先我们看到这个题目,我们不难想到用%的方法,假如现在给一个数字1234,要如何打印出1 2 3 4 这四个数字呢?首先就是很容易想到1234%10=4,这时候我们就得到了4,然后1234/10=123(默认取整),然后再用123%10=3,这时候我们就得到了3…按照这个思路我们的代码就能实现,后面我还会再加上图片解释,方便大家进一步理解: 内联代码片

void get(int n)
{
	if (n > 9)
	{
		get(n / 10);
	}

	printf("%d ", n % 10);
}


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

在这里插入图片描述
在这里插入图片描述

三. 递归与迭代

(1)递归是⼀种很好的编程技巧,但是和很多技巧⼀样,也是可能被误⽤的,就像举例1⼀样,看到推导的公式,很容易就被写成递归的形式,为大家解释一下,我们的第一个例子求n的阶乘,我们用递归的方法很容易算出来,但是我们可以自己操作一下,如果数值小的话,计算结果是很快出来,但是如果我们的数值偏大,假如我们输入50,那么计算结果就会很慢,原因就是 Fact函数是可以产生正确的结果,但是在递归函数调用的过程中涉及⼀些运行时的开销。

  • 在C语言中每⼀次函数调用,都需要为本次函数调用在内存的栈区,申请⼀块内存空间来保存函数调用期间的各种局部变量的值,这块空间被称为运行时堆栈,或者函数栈帧
  • 函数不返回,函数对应的栈帧空间就⼀直占用,所以如果函数调用中存在递归调用的话,每⼀次递归函数调用都会开辟属于自己的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。所以如果采用函数递归的方式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出(stackoverflow)的问题。

(2)所以如果不想使用递归,就得想其他的办法,通常就是迭代的方式(通常就是循环的方式)比如我们举的第一个例子计算n的阶乘,也是可以产⽣1~n的数字累计乘在⼀起的。
在这里插入图片描述

上述代码是能够完成任务,并且效率是比递归的方式更好的。事实上,我们看到的许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更加清晰,但是这些问题的迭代实现往往比递归实现效率更高。但是当⼀个问题非常复杂,难以使用迭代的方式实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。所以我们不能说是递归更便捷还是迭代更便捷,我们更多的要去思考问题本身。

3.1 求第n个斐波那契数

我们也能举出更加极端的例⼦,就像计算第n个斐波那契数,是不适合使⽤递归求解的,但是斐波那契数 (1 1 2 3 5 8 13…前两个数相加) 的问题通过是使⽤递归的形式描述的,如下:在这里插入图片描述
当我们n输⼊为50的时候,需要很长时间才能算出结果,这个计算所花费的时间,是我们很难接受的,这也说明递归的写法是非常低效的,那是为什么呢?其实递归程序会不断的展开,在展开的过程中,我们很容易就能发现,在递归的过程中会有重复计算,而且递归层次越深,冗余计算就会越多。在这里插入图片描述
就像上面的图片上展示的,计算一个数值,就要将它拆分成另外两个数,以此类推,会循环很多很多次,也造成了巨大的计算量,所以在有些时候我们不妨试试另一种方法,例如迭代的方法,其实循环也算是迭代的一种,下图计算将递归的方法转换成迭代的方式去实现这个代码,效率就要高出很多了。有时候,递归虽好,但是也会引⼊⼀些问题,所以我们⼀定不要迷恋递归,适可而止就好。在这里插入图片描述

以上就是关于递归的一些初级的理解,在后期我也会为大家继续写更多关于递归的知识,以及一些深入的了解。

标签:函数,迭代,int,代码,C语言,递归,我们
From: https://blog.csdn.net/OKkankan/article/details/139484740

相关文章

  • 详解python中的pandas.read_csv()函数
    ......
  • 2024-06-05 拷贝、函数、装饰器、迭代生成器
    一、浅拷贝lists=[1,2,[6]]内存空间不同,浅拷贝内容不变 new_lists=copy(lists)lists.append(7)print(lists,new_lists)//[1,2,[6],7][1,2,[6]]改变列表中内容,内存空间相同,数值改变new_lists=copy(lists)lists[-1].append(7)print(lists,new_lists)//[......
  • 【C语言】预处理详解(中卷)
    前言预处理完整系列推荐阅读顺序:预处理详解(上卷)——宏(上卷)——宏(下卷)——预处理详解(中卷)——预处理详解(下卷)本文接着讲预处理相关的内容。#和###运算符#可以将宏的一个参数转换成字符串字面量。它仅允许出现在带参数的宏的替换列表中。#运算符所执行的操作可以理解为“......
  • Excel常用函数速通
    和GPT学的,对话链接https://chatgpt.com/share/614a056c-01a6-49da-a585-b32084865349常用函数文件分享附xlsx练习表VLOOKUP(lookup_value,table_array,col_index_num,[range_lookup])VLOOKUP(查找值,查找区域,返回列序号,[精确匹配])SUBTOTAL(function_num,ref1,[r......
  • 【C语言】分支与循环(下)
     目录 6. while循环7. for循环8. do-while循环9. break和continue循环10. 循环的嵌套11. goto语句正文开始——6. while循环  C语言提供了三种循环,while就是其中一种。while语句的语法结构与if语句非常相似。6.1 if和while的对......
  • 算法 | 剪枝函数以及几种形式&回溯法和分支限界法的区别&算法特性&分支限界法的思想&
    whatis剪枝函数?是对该问题能否得到最优解或者可行解的约束限界函数:最优解约束函数:可行解回溯法和分支限界法的区别:异:回溯法分支限界法一次生成/扩展一个结点一次生成所有的孩子结点BFSDFS/最小耗费优先找到所有解找到最优解同:均需要定义解空间,解空间的组织结构一般......
  • 「笔记」递归算法复杂度分析
    目录写在前面递归算法形式递归树大力求和主定理MasterTheorem典题1234写在最后写在前面可恶的算法分析与设计!!!递归算法形式对于一个输入规模为\(n\)的递归算法,每次均为将整个问题划分为\(a\)个规模为\(\frac{n}{b}\)的子问题,回溯时将所有子问题合并需要\(f(n)\)的时......
  • c语言——字符函数与字符串函数
    文章目录一字符函数(1)字符分类函数:(2)字符转换函数:二字符串函数(1)strlen函数的使用与模拟(2)strcpy函数的使用与模拟(3)strcmp函数的使用与模拟(4)strcat函数的使用与模拟两组函数的区别:(5)strncpy函数(6)strncmp函数的使用(7)strncat函数的使用(8)strstr函数的使用与模拟(9)strtok函数......
  • 【C语言】写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换
    思路:10的二进制是00000000000000000000000000001010,然后交换奇数位和偶数位那么就是第一位和第二位交换,第三位和第四位交换,以此类推解题步骤:(1)将00000000000000000000000000001010的奇数位保留,偶数位变为0则变成00000000000000000000000000000000(2)将00000000000000000000......
  • C++缺省参数、缺省参数的概念、缺省参数的分类、函数重载、函数重载的概念、C++支持函
    文章目录前言一、缺省参数1.缺省参数的概念2.缺省参数的分类二、函数重载1.函数重载的概念2.C++支持函数重载的原理三、引用1.引用的概念2.引用的特性3.常引用4.引用的使用场景5.传值和传引用效率比较6.引用和指针的区别总结前言C++缺省参数、缺省参数......