精华内容
下载资源
问答
  • c语言中递归函数
    2021-05-21 03:19:41

    匿名用户

    1级

    2010-12-11 回答

    递归(recursion)就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。

    递归通常用来解决结构自相似的问题。所谓结构自相似,是指构成原问题的子问题与原问题在结构上相似,可以用类似的方法解决。具体地,整个问题的解决,可以分为两部分:第一部分是一些特殊情况,有直接的解法;第二部分与原问题相似,但比原问题的规模小。实际上,递归是把一个不能或不好解决的大问题转化为一个或几个小问题,再把这些小问题进一步分解成更小的问题,直至每个小问题都可以直接解决。因此,递归有两个基本要素:

    (1)边界条件:确定递归到何时终止,也称为递归出口。

    (2)递归模式:大问题是如何分解为小问题的,也称为递归体。递归函数只有具备了这两个要素,才能在有限次计算后得出结果

    汉诺塔问题:对汉诺塔问题的求解,可以通过以下3个步骤实现:

    (1)将塔上的n-1个碟子借助塔C先移到塔B上;

    (2)把塔A上剩下的一个碟子移到塔C上;

    (3)将n-1个碟子从塔B借助塔A移到塔C上。

    在递归函数中,调用函数和被调用函数是同一个函数,需要注意的是递归函数的调用层次,如果把调用递归函数的主函数称为第0层,进入函数后,首次递归调用自身称为第1层调用;从第i层递归调用自身称为第i+1层。反之,退出第i+1层调用应该返回第i层。采用图示方法描述递归函数的运行轨迹,从中可较直观地了解到各调用层次及其执行情况,具体方法如下:

    (1)写出函数当前调用层执行的各语句,并用有向弧表示语句的执行次序;

    (2)对函数的每个递归调用,写出对应的函数调用,从调用处画一条有向弧指向被调用函数入口,表示调用路线,从被调用函数末尾处画一条有向弧指向调用语句的下面,表示返回路线;

    (3)在返回路线上标出本层调用所得的函数值。n=3时汉诺塔算法的运行轨迹如下图所示,有向弧上的数字表示递归调用和返回的执行顺序

    三、递归函数的内部执行过程

    一个递归函数的调用过程类似于多个函数的嵌套的调用,只不过调用函数和被调用函数是同一个函数。为了保证递归函数的正确执行,系统需设立一个工作栈。具体地说,递归调用的内部执行过程如下:

    (1)运动开始时,首先为递归调用建立一个工作栈,其结构包括值参、局部变量和返回地址;

    (2)每次执行递归调用之前,把递归函数的值参和局部变量的当前值以及调用后的返回地址压栈;

    (3)每次递归调用结束后,将栈顶元素出栈,使相应的值参和局部变量恢复为调用前的值,然后转向返回地址指定的位置继续执行。

    上述汉诺塔算法执行过程中,工作栈的变化如下图所示,其中栈元素的结构为(返回地址,n值,A值,B值,C值),返回地址对应算法中语句的行号,分图的序号对应图中递归调用和返回的序号

    我可以帮助你,你先设置我最佳答案后,我百度Hii教你。

    更多相关内容
  • C语言中递归函数的设计.ppt
  • C语言中递归函数的设计归算法是程序设计常用的算法之一。本文从几个例子出发,分析了C语言中常见的递归函数的设计方法,并简要介绍了设计递归函数的步骤及注意事项。
  • C语言中递归函数的应用.pdf
  • C语言递归函数设计授课PPT,C程序结构是函数模块结构,C程序是由一个或多个函数构成的,是函数的集合。函数具有相对独立的特定功能,是程序的基本单位,因此,在C语言教学,函数这一章(大部分教材把函数作为一章)...
  • 关于C语言中递归函数教学的探讨.pdf
  • C语言中递归函数的设计.zip
  • C语言中递归函数的教学方法导语:函数递归基于分治法思想,将复杂的大规模问题转化为小规模问题进行求解,在算法设计具有重要的理论意义和实用价值,是C语言教学的难点。下面就由小编为大家介绍一下C语言中递归...

    C语言中递归函数的教学方法

    导语:函数递归基于分治法思想,将复杂的大规模问题转化为小规模问题进行求解,在算法设计中具有重要的理论意义和实用价值,是C语言教学的难点。下面就由小编为大家介绍一下C语言中递归函数的教学方法,欢迎大家阅读!

    6b387b2afa8de0f05a6d850ece86637c.png

    1.引言

    C语言是一种语法简洁紧凑、运算符丰富、可移植性强、目标程序执行效率高的强数据类型语言,近年来在国内得到迅速的推广应用。作为我校信息类本科教学的入门语言,C语言是汇编语言、计算机原理、单片机程序设计等其他后继课程的基础,对整个教学过程具有重要的作用。

    所有的C语言程序都由函数组成。在函数的调用中,直接或间接地调用自身的函数称为递归函数,相应的算法称为递归算法。在计算机算法设计与分析中,递归算法是一类较重要的算法,递归的使用往往使函数的定义和算法的描述简洁且易于理解。

    2.递归的基本原理

    对于任何可以用计算机求解的问题,其求解难度与计算时间都与问题的规模有关。若一个规模较大的且难以直接解决的问题能够分解为k个规模较小的子问题,并且这些子问题互相独立且与原问题相同,那么可以通过对这些子问题进行分别求解,然后将各个子问题的解合并,得到原问题的解。其中P代表原始问题,P1、P2…Pk是比原始问题的规模|P|更小的子问题,Merge函数将子问题的解y1、y2…yk进行合并。

    假设原始问题规模为n,子问题P1、P2…Pk的规模为n/m,分解阈值n0=1,且AdHoc函数求解规模为1的问题耗费1个单位时间。再设合并函数Merge的时间复杂度为f此时递归算法具有多项式的计算复杂度,其阶数由子问题的`划分数目k和子问题的规模n/m共同决定。

    3.教学实例分析

    函数的递归是C语言教学中的一个难点,本节根据上面给出的递归程序结构,通过一组从简单到复杂的实例,逐步引导学生掌握递归程序编写的技巧。

    实例1(阶乘问题):计算整数n的阶乘。

    分析:该问题可使用下述递归结构进行求解:

    (1)当n=1时,可以直接计算n!=1;

    (2)当n>1时,n!可以通过对1个小规模的子问题(n-1)!的求解得到,也即n!=(n-1)!*n。

    实例2(Hanoi塔问题):设a、b、c是三个塔座。开始时,在a座处自上而下、从小到大地叠放n个圆盘,编号分别为1、2、…n,如图1所示。现要求将a座处的所有圆盘按同样的次序堆叠到b座上,并且要求:(1)每次只能移动1个圆盘;(2)任何时候都不允许将大盘压在小盘的上方。

    分析:该问题可使用下述递归结构进行求解:

    (1)当n=1时,直接将盘从a座移动到b座;

    (2)当n>1时,将圆盘按下列方法移动(见图2):

    ①将a座上的n-1个盘移动到c座;

    ②将a座的第n个盘移动到b座;

    ③将c座上的n-1个盘移动到b座。

    根据以上分析,可以写出如下的程序:

    实例3(排序问题):对n个元素的整型数组array进行排序。

    分析:该问题可使用下述递归结构进行求解:

    (1)当n=1时,直接输出排序结果;

    (2)当n>1时,按下列方法进行排序:

    ①将array分成大小基本相同的两部分;

    ②对两个子数组分别进行排序;

    ③将两个排序后的子数组进行合并。

    其中参数left和right分别代表当前数组的第1个元素和最后一个元素的下标。

    对于该排序算法,子问题的数目k=2,规模n/m = n/2。因为函数Merge的合并操作可以在线性时间内完成,所以由(3)式可以得到相应的时间复杂度为

    T(n)=O(nlogn)(4)

    4.结语

    在C语言教学中,函数的递归一直是教学的重点和难点。本文首先从理论上给出递归的程序结构,然后以该结构为指导,通过一组程序实例,引导学生掌握递归程序的编写技巧,理解应用分治法解决复杂问题的思想。实践证明,本方法在课堂教学中取得较好的效果。

    展开全文
  • C语言递归函数的执行与求解导语:函数的递归调用是在调用一个函数的执行过程,直接或间接地调用该函数本身,使用递归函数的程序结构清晰,简单、易懂。下面就由小编为大家介绍一下C语言递归函数的执行与求解,欢迎...

    C语言递归函数的执行与求解

    导语:函数的递归调用是在调用一个函数的执行过程中,直接或间接地调用该函数本身,使用递归函数的程序结构清晰,简单、易懂。下面就由小编为大家介绍一下C语言递归函数的执行与求解,欢迎大家阅读!

    1 递归函数

    C语言的特点之一就在于允许函数的递归调用,即允许在函数内部直接或间接的调用函数自身,被调用的函数被称为递归函数。递归调用有直接递归调用和间接递归调用两种形式,递归函数常用于解决那些需要分多次求解且每次求解过程都基本类似的问题。构造递归函数的关键在于寻找递归算法和终结条件。递归算法就是解决问题所采取的方法和步骤,一般只要对问题的若干次求解过程进行分析和归纳,找出每一次求解过程之间的规律性,就可归纳出递归算法,终结条件是为了终结函数的递归调用而设置的一个条件或规则。递归调用的一般形式为:

    函数类型 函数名(参数列表)

    {

    ,,,,,

    函数名(参数列表)

    …..

    }

    2 递归条件

    使用递归调用编写程序时,要注意以下几点:

    (1)可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式,只是所处理的对象具有一定的规律性。也就是说解决问题的方法相同,调用函数的参数有规律的递增或递减。

    (2)递归函数必须有一个终止处理条件,即必须有一个明确的结束条件,必须在适当的时候能够结束递归调用,否则会使程序陷入死循环,导致系统崩溃。

    (3)有些使用递归算法求解的问题也可使用普通循环算法来实现,相较于循环程序,递归程序结构简单,逻辑清晰,但运行效率低,故在有其他算法可以代替的情况下,要尽量避免使用递归算法编写程序。

    3 递归实例

    例:使用递归方法求n!。

    在数学上n!=1×2×3×…×n-1×n,我们可以写成以下形式

    1 当n=0或n=1时

    n!=

    (n-1)!×n 当n>1时

    根据以上形式,可以写出如下递归调用程序:

    int f(n)

    {

    if(n==1||n==0)

    return 1;

    else

    return f(n-1)*n;

    }

    int main()

    {

    int n;

    scanf(“%d”,&n);

    if(n<0)

    printf(“data error!”);

    else

    printf(“%d”,f(n));

    return 0;

    }

    4 递归函数执行过程

    递归调用之所以能够实现,是因为函数在每一次执行过程中,都会把自己所有形参变量和局部变量复制一个副本,压入栈中,这些副本分别位于栈中不同的内存空间,和函数的其他执行过程毫不相干,这种机制使得递归调用成为可能。一个递归函数的执行过程类似于调用函数和被调用函数是同一个函数的多层嵌套调用,因此,和递归函数的执行过程密切相关的一个重要概念就是递归函数运行的层次。假设调用该递归函数的主函数为第0层,则从主函数调用递归函数则进入第一层;从第n层调用本函数则进入“下一层”,即第n+1层。反之,退出第n层递归调用应返回至“上一层”,即第n-1层。

    在递归函数的执行过程中,另一个非常重要的概念是“递归工作栈”的使用,当一个函数(调用者)调用另外一个函数(被调用者)时,系统会把调用者的所有实在参数,被调用者的形式参数、局部变量,以及调用者的返回地址等信息全部压入“递归工作栈”暂存,当被调用者执行完毕时,系统会从栈中弹出被调用者的形式参数和局部变量,释放被调用者所占用的数据区,接着被调用者返回,然后系统从栈中弹出调用者的返回地址,和实在参数等信息,此时调用者函数可以继续执行下去。

    5 求解方法

    我们通过举例来说具体说明递归函数的求解,比如在主函数中输入n的值为5,即求5!,则函数的求解过程可以用图1-1表示:

    以上问题的具体求解过程描述如下:①调用函数f(5),n=5,函数f(5)的返回结果是f(4)*5,系统暂存f(5)的形参和中间计算结果,然后转去调用函数f(4)。②执行函数f(4),n=4,函数f(4)的返回结果是f(3)*4,系统暂存f(4)的形参和中间计算结果,然后转去调用函数f(3)。③执行函数f(3),n=3,函数f(3)的返回结果是f(2)*3,系统暂存f(3)的形参和中间计算结果,然后转去调用函数f(2)。④执行函数f(2),n=2,函数f(2)的返回结果是f(1)*2,系统暂存f(2)的形参和中间计算结果,然后转去调用函数f(1)。⑤执行函数f(1),n=1,函数f(1)返回结果1,f(1)执行完毕,系统释放f(1)的.形参和中间变量所占的数据区,然后返回到调用函数f(1)处。⑥函数f(2)返回结果f(1)*2=1*2=2,f(2)执行完毕,系统释放f(2)的形参和中间变量所占的数据区,然后返回到调用函数f(2)处。⑦函数f(3)返回结果f(2)*3=2*3=6,f(3)执行完毕,系统释放f(3)的形参和中间变量所占的数据区,然后返回到调用函数f(3)处。⑧函数f(4)的返回结果f(3)*4=6*4=24,f(4)执行完毕,系统释放f(4)的形参和中间变量所占的数据区,然后返回到调用函数f(4)处。⑨函数f(5)返回结果f(4)*5=24*5=120,f(5)执行完毕,系统释放f(5)的形参和中间变量所占的数据区,然后返回到调用函数f(5)处,即main函数,此问题求解结束。

    6 结束语

    函数的递归调用,可以把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归算法只需用少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了程序的代码量并增强了程序的可读性。但在求解过程中容易出错和混淆,了解递归函数的执行过程,并借助于图示化的方法、,即可正确、快速求解递归函数。

    展开全文
  • C语言详解:函数递归专题

    万次阅读 多人点赞 2021-08-17 14:19:32
    函数递归 函数递归的定义和优缺点 程序调用自身的行为就是递归。可以直接或间接的调用,本质是把复杂的问题转化为一个规模小的问题。递归一般只需少量的代码就可描绘出多次重复计算。其主要思考方式在于大事化小。 ...

    函数递归

    函数递归的定义和优缺点

    程序调用自身的行为就是递归。可以直接或间接的调用,本质是把复杂的问题转化为一个规模小的问题。递归一般只需少量的代码就可描绘出多次重复计算。其主要思考方式在于大事化小

    优点是为具有某些特征的编程问题提供了最简单的策略,缺点是层层调用,算法的复杂度可能过高,以致于快速耗干了计算机的内存资源,不方便阅读和维护等。

    递归的使用场景及必要条件

    使用场景

    1. 能够要求转化为新的问题,且二者解决方法相同,所处理的对象存在规律变化。
    2. 非递归比较麻烦,而递归很简单。
    3. 有模板或是公式可以直接套用,不会出现明显问题。

    必要条件

    • 明确存在限制条件
    • 每次递归越来越逼近条件

    递归的细节说明

    • 每级递归都有自己的变量,可能名称相同,但是其值不同。

      递归调用时,系统自动保留当前函数的参数变量。每次调用系统都会为函数开辟相应的空间。

    • 每次调用都要返回值,递归执行结束后,控制权传回到上一级函数。

      调用结束后,系统释放本次调用所开辟的空间,程序返回到上一次的调用点,同时获得初进该级调用的参数。

      每级递归必须逐级返回,不可跳跃或间断。

    • 函数中递归语句之前的代码,按被调函数的顺序执行,递归之后的代码,与被调函数相反的顺序执行。

    递归的习题讲解

    1打印整数每一位

    用递归的方式,实现打印一个整数的每一位的功能。

    输入输出示例

    输入:1234

    输出:1 2 3 4

    解题思路

    print(1234)
    = = = print(123)+4
    = = = print(12)+3+4
    = = = print(1)+2+3+4
    = = = printf(1)+2+3+4

    这便是前面使用场景中所写的,将题目要求问题转化为新的问题,且变量有规律的变化

    代码逻辑

    n是不是个位数,递推调用n / 10

    n是个位数,回归打印n % 10

    void Print(int n) 
    {
    	if (n > 9)
    	{
    		Print(n / 10);
    	}
    	printf("%d ", n%10);
    }
    int main()
    {
    	int num = 0;
    	scanf("%d", &num);
    	Print(num);	
    	return 0;
    }
    
    2递归和非递归求n阶乘

    用递归和非递归的方法,分别实现求n的阶乘的功能(不考虑溢出)。

    输入输出示例

    输入:5

    输出:120

    解题思路

    n ∗ n − 1 ∗ n − 2 ∗ n − 3 ∗ … ∗ 1 n*n-1*n-2*n-3*…*1 nn1n2n31

    代码逻辑

    f a c ( n ) = n ∗ f a c ( n − 1 ) , n > 0 fac(n) = n * fac(n-1) , n>0 fac(n)=nfac(n1),n>0

    f a c ( n ) = 1 , n = 0 fac(n) = 1 , n=0 fac(n)=1,n=0

    int fac(int n)//非递归
    {
    	int ret = 1;
    	for (int i = 1; i <= n; i++)
    	{
    		ret *= i;
    	}
    	return ret;
    }
    int fac(int n)//递归
    {
    	if (n > 0)
    		return n * fac2(n - 1);
    	else
    		return 1;
    }
    int main()
    {
    	int n = 0;
    	scanf("%d", &n);	
    	printf("%d\n", fac(n));
    	return 0;
    }
    
    3strlen函数模拟
    输入输出示例

    输入:abcdef

    输出:6

    解题思路

    strlen(abcdef\0)
    1+strlen(bcdef\0)
    1+1+strlen(cdef\0)
    1+1+1+strlen(def\0)
    1+1+1+1+strlen(ef\0)
    1+1+1+1+1+strlen(f\0)
    1+1+1+1+1+1+strlen(\0)

    代码逻辑

    若 ∗ c h ≠ 0 , s t r l e n ( a r r ) = 1 + s t r l e n ( a r r + 1 ) 若 *ch≠0 , strlen(arr) = 1 + strlen(arr+1) ch=0,strlen(arr)=1+strlen(arr+1)
    若 ∗ c h = 0 , s t r l e n ( a r r ) = 0 若*ch=0 , strlen(arr) = 0 ch=0,strlen(arr)=0

    my_strlen求字符串长度函数解析

    int my_strlen(char* ch)
    {
    	if (*ch != '\0')
    	{
    		return 1 + my_strlen(ch + 1);
    	}
    	return 0;
    }
    int main()
    {
    	char ch[20] = { 0 };
    	scanf("%s", &ch);
    	printf("%d", my_strlen(ch));
    	return 0;
    }
    
    4逆序字符串

    不开辟额外空间的情况下,不使用字符串库函数,递归实现字符串反向排列,而不是倒序打印。

    输入输出示例

    输入:abcdef

    输出:fedcba

    解题思路

    abcdef

    递推:(先把后面赋值给前面,后面用覆盖\0)

    $ \Rightarrow$ f b c d e \0

    ⇒ \Rightarrow f e c \0\0

    ⇒ \Rightarrow f e d \0\0\0

    回归:(把前面转移出去的字符对应赋值给\0)

    $ \Rightarrow$ f e d c \0\0

    ⇒ \Rightarrow f e d c b \0

    ⇒ \Rightarrow f e d c b a

    递归逆序字符串图示

    代码逻辑

    reverse("abcdef\0") 交换a和f+reverse("f bcde\0\0") 交换a和f+交换b和e+reverse("fe cd\0\0\0") 交换a和f+交换b和e+交换c和d+reverse("fed \0\0\0\0")

    • 交换两个字符
      1. 将在前的字符先放到一边存着
      2. 把在后的字符赋值到前面的位置
      3. 再把后面的位置对应覆盖为\0
    • 原在前字符替换\0
      1. 把事先存好的在前的字符对应替换到\0的位置上

    递归逆序字符串代码详细解析

    void reserve_string1(char* ch)//指针
    {
    	char* left = ch;
    	char* right = ch + strlen(ch) - 1;
    	while (left < right)
    	{
    		char tmp = *left;//不能交换地址,只能交换内容
    		*left = *right;
    		*right = tmp;
    		left++;
    		right--;
    	}
    }
    void reserve_string2(char* ch)//数组
    {
    	int left = 0;
    	int right = strlen(ch) - 1;
    	while (left < right)
    	{
    		char tmp = ch[right];
    		ch[right] = ch[left];
    		ch[left] = tmp;
    		left++;
    		right--;
    	}
    }
    
    void reverse_string3(char* ch)//递归
    {
    	char* left = ch;
    	char* right = ch + strlen(ch) - 1;
    
    	if (*ch != '\0')
    	{
    		char tmp = *left;//提取
    		*left = *right;//赋值
    		*right = '\0';//赋\0
    
    		reverse_string3(ch+1);//ch+1,而不是ch++
    
    		*right = tmp;//赋值
    	}
    }
    int main()
    {
    	char ch[20] = "abcdef";
    	//char* ch = "abcdef";//err - 常量字符串不可修改
    	reverse_string3(ch);
    	printf("%s\n", ch);
    
    	return 0;
    }
    
    5递归实现数字各位之和

    写一个递归函数DigitSum(),输入一个非负整数,返回组成它的数字之和

    输入输出示例

    输入:1234

    输出:10

    解题思路

    1234
    DigitSum(123)+4
    DigitSum(12)+3+4
    DigitSum(1)+2+3+4

    1+2+3+4

    1234%10=4
    1234/10=123

    123%10=3
    123/10=12

    12%10=2
    12/10=1

    1%10=1
    1/10=0

    一个数模10得到尾数,除10得到尾数前面的数字

    通过不断的除10模10,就可以把每一位数字放到末尾,从而得到每一位数字

    代码逻辑

    若n不为个位数,先%10得到尾数,再/10

    一定要有递归的出口,即当n为个位数时,函数返回n

    
    
    int DigitSum(int n)
    {
    	if (n > 9)
    		return DigitSum(n / 10) + n % 10;
    	else
    		return n;//递归的出口
    }
    int main()
    {
    	int n = 0;
    	scanf("%d", &n);
    	printf("%d\n", DigitSum(n));
    
    	return 0;
    }
    
    6求n的k次幂

    输入两个整数分别代表底数和次幂,递归实现n的k次幂的功能。

    输入输出示例

    输入:2 3

    输出:8

    解题思路

    k>0时,函数返回n*power(n,k-1)

    k=0时,函数返回1,这是程序的出口,是程序递归到最后必须要计算的值

    代码逻辑

    n k = n ∗ n k − 1 , k > 0 n^k = n * n^{k-1} ,k > 0 nk=nnk1,k>0
    n k = 1 , k = 0 n^k = 1 , k = 0 nk=1,k=0

    double power(int n,int k)
    {
    	if (k > 0)
    		return n * power(n, k - 1);
    	else if (k == 0)
    		return 1.0;//递归的出口k=0
    	else
    		return 1.0 / power(n, -k);
    }
    int main()
    {
    	int n = 0;
    	int k = 0;
    	scanf("%d%d", &n, &k);
    	printf("%lf\n", power(n, k));
        return 0;
    }
    
    7递归求斐波那契数列

    递归和非递归分别实现求第n个斐波那契数

    输入输出示例

    输入:5

    输出:5

    解题思路

    1 1 2 3 5 8 13 21 34 55 89 . . . 1\quad 1\quad 2\quad 3\quad 5\quad 8\quad 13\quad 21\quad 34\quad 55\quad 89\quad ... 1123581321345589...

    代码逻辑

    递归:

    F i b ( n ) = F i b ( n − 1 ) + F i b ( n − 2 ) , n > 2 Fib(n) = Fib(n-1) + Fib(n-2) , n>2 Fib(n)=Fib(n1)+Fib(n2),n>2
    F i b ( 1 ) = F i b ( 2 ) = 1 Fib(1) = Fib(2) = 1 Fib(1)=Fib(2)=1

    非递归:

    上一次的b换成这一次的a

    上一次的c换成这一次的b

    如此循环,就可以从前往后一个一个求。

    非递归求斐波那契数列示例

    int Fib(int n)
    {
    	if (n > 2)
    		return Fib(n - 1) + Fib(n - 2);
    	else
    		return 1;
    }
    

    但是这个方法效率是非常低的,当数字特别大时,层层拆分下来,时间效率是 O ( 2 n ) O(2^n) O(2n)

    根据公式可知,第三个斐波那契数可由前两个得到,我们利用这个规律

    int Fib(int n)
    {
    	if (n <= 2)
    		return 1;
    	int a = 1;
    	int b = 1;
    	int c = 1;//n=3时不用运算
    	while (n >= 3)//从头开始移动n-2次,n=3时不用
    	{
            c = a + b;
    		a = b;//b赋值给a
    		b = c;//c赋值给b		
    		n--;
    	}
    	return c;
    }
    
    int main()
    {
    	int n = 0;
    	scanf("%d", &n);
    	printf("%d",Fib(n));
        
    	return 0;
    }
    

    经典问题

    汉诺塔问题

    汉诺塔,小时候游戏机上经常看别人玩的,自己玩到三四局就玩不下去了的那款游戏。当然如果你觉得非常简单,小时候能玩的行云流水,那你有本事到我面前说,礼貌谢谢(狗头保命)。

    游戏规则

    有三根柱子,分别为A、B、C ,A柱上从上到下依次排列着由小到大的圆盘,我们需要把圆盘从A柱按照同样的摆放顺序放到C柱上,期间我们可以借助B柱。

    • 每次只能挪动一个且是最上面的圆盘
    • 按照从上到下依次是由小到大的顺序摆放。
    解题思路

    假设由N个盘子,只需要考虑第 N N N个盘子和其上 N − 1 N-1 N1个盘子的整体。显然思路就是,第 N N N个是要放在 C C C柱上的,

    1. 首先将 N − 1 N-1 N1个整体是先放在 B B B柱上;
    2. 其次将第 N N N个放在 C C C柱上;
    3. 最后将 N − 1 N-1 N1个整体放到 C C C柱上。

    即:第 N N N A → B A\rightarrow B AB N − 1 N-1 N1个整体 A → B → C A\rightarrow B\rightarrow C ABC 。然后再考虑 N − 1 N-1 N1个中把第 N − 1 N-1 N1个当作最后一个,其上 N − 2 N-2 N2个当作整体,到最后只剩一个直接放到 C C C柱上。这便是递归的整体思路。

    在这里插入图片描述

    void move(int n, int x, int z)
    {
    	printf("%d盘:%c->%c\n", n, x, z);
    }
    void hannoi(int n, char x, char y, char z)
    {
    	if (n == 1)
    		move(n, x, z);
    	else
    	{
    		hannoi(n - 1, x, z, y);
    		move(n, x, z);
    		hannoi(n - 1, y, x, z);
    	}
    }
    int main()
    {
    	int input = 0;
    	do 
    	{
    		printf("输入盘数开始测试(0. 退出测试)\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 0:
    			break;
    		default:
    			hannoi(input, 'A', 'B', 'C');
    			break;
    		}
    	} while (input);
    	return 0;
    }
    
    青蛙跳台阶
    游戏规则

    初阶版本

    ​ 青蛙一次可以跳一级台阶,也可以跳两级台阶。求该青蛙跳n级台阶共有多少种跳法?

    进阶版本

    ​ 青蛙一次可以跳一级台阶,也可以跳两级台阶,……,也可以跳n级台阶,求该青蛙跳上n级台阶的跳法种数。

    青蛙跳台阶思维示例

    解题思路

    我们反向思考,当青蛙跳到最高阶 N N N阶时,他是怎么跳到第 N N N阶的呢?

    有两种情况,

    • 从第 N − 1 N-1 N1阶,跳到第 N N N阶,最后一次跳一阶。
    • 从第 N − 2 N-2 N2阶,跳到第 N N N阶,最后一次跳两阶。

    图中用灰框框出的部分,是最后一次跳一阶的,其余的是最后一次跳两阶的。

    很显然,除了这两种情况,别无他法。所以计算青蛙

    跳到 N N N阶的方法数 = = = N − 1 N-1 N1阶的方法数 + + + N − 2 N-2 N2 阶的方法数。

    同样,图中用灰框框出的部分,也代表的是跳 N − 1 N-1 N1阶的方法数,其余的是跳 N − 2 N-2 N2 阶的方法数。

    这其实就是斐波那契数列。

    int fib(int n)
    {
    	if (n > 1)
    		return fib(n - 1) + fib(n - 2);
    	else
    		return 1;
    }
    
    展开全文
  • C语言函数递归

    2022-03-26 23:06:11
    所谓递归函数是指一个函数的函数体直接调用或间接调用了该函数自身的函数。 递归函数调用的执行过程分为两个阶段。 递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。 回归阶段:按...
  • C语言函数递归(详解)

    千次阅读 多人点赞 2022-02-07 10:56:02
    1.从调用自身层面:函数递归就是函数自己调用自己。 2.从编程技巧层面:一种方法(把一个大型复杂的程序转换为一个类似的小型简单的程序),这种方法的主要思想就是把大事化小。 ????????递归的两个必要条件 ...
  • 所谓中间递归,就是发生递归的位置在函数体的中间,而不是末尾。 尾递归在逐层退出时除了 return 语句,一般不再执行其他操作;而中间递归在逐层退出时还要执行一些其他的操作,所以比较复杂。 下面我们以字符串反转...
  • C语言递归函数return问题

    千次阅读 2019-07-06 17:00:30
    今日偶遇一道c语言递归的题,因为之前对此也是一知半解,这次仍然没有做对。认真分析后,在此做下笔记。题目如下: 右侧是输出结果。 分析: x=3,调用join(x),x++后,再次调用join(x),直到调用join(7)...
  • C语言——函数递归

    2022-02-23 16:38:36
    函数的声明和定义函数声明: 1.告诉编译器有一个函数叫...程序调用自身的编程技巧称为递归(recursion),递归作为一种算法在程序设计语言广泛应用。一个过程或函数在其定义或说明有直接或间接调用自身的一种方...
  • “多层递归”是我自己起的名字,意思是在一个函数里面多次调用自己。 多层递归的调用关系比较复杂,整体上看起来像一颗倒立的树:对于双层递归,树的每个节点有两个分叉;对于三层递归,树的每个节点有三个分叉;...
  • C语言递归函数实现汉诺塔
  • C语言 函数递归例题解析

    万次阅读 多人点赞 2018-05-08 14:37:44
    模拟实现strlen()函数。 3.求n的阶乘 4.斐波那契数列 总结 1.接受一个整形值(无符号),把它转换为 字符并打印它 void fun(int x) { if (x &gt; 9) { fun(x/10); } printf("%d\n", x%10...
  • 关于C语言中递归函数

    万次阅读 多人点赞 2019-03-14 11:09:34
    递归实例: #include &lt;stdio.h&gt; void up_and_down(int); int main(void) { up_and_down(1); return 0; } void up_and_down(int n) { printf("Level %d: n location %p\n", n, &...
  • c语言递归函数的使用方法

    千次阅读 2021-05-20 10:34:09
    c语言递归函数的使用方法发布时间:2020-06-11 09:39:53来源:亿速云阅读:157作者:Leah这篇文章给大家分享的是c语言递归函数的使用方法。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。递归...
  • C语言递归函数实例分析 斐波那契数列 问题描述:斐波那契数列是以1为首项,1为第二项,其他项都为前面两项之和的数列。如:1、1、2、3、5…求斐波那契数列的第n项。 实现方法:采用递归函数的方式,以此算出每项,...
  • 程序调用自身的编程技术称为递归。它通常把一个大型问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可以描述出解题过程所需要的多次...在c语言中函数本身是在栈上开辟空间的,
  • C语言函数递归调用PPT课件.pptx
  • 11.函数(C语言)+递归函数(超清晰图解递归)

    千次阅读 多人点赞 2021-11-01 09:41:05
    函数1.函数是什么?2.库函数1)库函数的基本知识2)初识几个库函数3.自定义函数自定义函数的组成4.函数参数1 )实际参数(实参):2) 形式参数(形参):5....1)函数是一个大型程序的某部分代码, 由一
  • 以下代码头文件可能没声明,还请读者自己声明一下。 1、递归方式实现打印一个整数的每一位 //int print(int n) //{ // if (n > 10) ...// print(n / 10);...2、递归和非递归分别实现求n的阶乘
  • 示例1:递归反向输出字符串 # include <stdio.h> void digui(char * p) { if(*p == '\0') return; else { digui(p+1); printf("%c",*p); } } int main() { digui("ABC\0"); printf("\n"); ...
  • C语言函数递归调用学习教案.pptx
  • 递归函数是一种强有力的技巧,用来解决某些问题很顺手,比如前面提到的求阶乘、求菲波那契数;但是和其他技巧一样,递归函数也是有缺陷的,而且这种缺陷是致命性的。 递归函数的空间开销 在程序占用的整个内存...
  • C语言递归函数求1累加到100求和

    千次阅读 2021-05-14 08:25:32
    C语言递归求1累加到100求和要实现的功能如下完整源代码实现如下 要实现的功能如下 1+2+3+…+100,用递归实现 完整源代码实现如下 #include <stdio.h> int x = 0; int function(int num); int main() { int ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 82,351
精华内容 32,940
关键字:

c语言中递归函数