4.10C++函数的递归调用

合集下载

函数的递归调用

函数的递归调用

函数的递归调用
函数的递归调用是一种技术,可用于构建更复杂的程序。

它是函数调用自己,或使用函数调用其他函数,以及由这些函数递归调用自身,构成了函数的递归调用。

在程序设计中,函数的递归调用可以帮助我们解决一些比较复杂的问题,可以更加高效地实现程序的执行任务。

在函数的递归调用过程中,函数对于自身调用的次数和内存消耗的多少是可控的。

函数的递归调用的基本概念是,函数在其函数体内部调用自身,而函数的递归调用重复多次,这种机制可以大大提高程序的效率,以及实现复杂程序的效果。

举个例子,假设我们要求计算指定范围内的数字之和,使用普通的加法运算无法满足需求,这时我们就可以通过函数的递归调用来实现这一操作。

通过函数的递归调用,我们可以将求和的操作解耦为两个部分:第一步,先找出指定数字的最后一个数字,将其加上已经求解过的结果;第二步,将比最后一个数字小的数字累加,将他们与第一步的结果相加即可得出最终结果。

此外,函数的递归调用还可以用于数学和算法中,比如排列组合、汉诺塔等等。

排列组合的问题可以使用递归调用的方法,每次都递归调用自身,排列出新的组合;汉诺塔的游戏也可以使用递归调用的方法,每次都将上层的圆盘移动到不同的柱子上,递归地完成游戏的解决。

函数的递归调用是一种很有用的技术,它可以使程序更加有效,
也可以帮助我们解决一些复杂的问题。

虽然函数的递归调用有一定的性能影响,但是也可以通过程序优化来解决,以得到更高性能的效果。

函数的递归调用是一种有效的程序设计方法,可以帮助我们更加高效地完成任务。

C语言进阶递归调用

C语言进阶递归调用

C语⾔进阶递归调⽤
C语⾔进阶递归调⽤
我们先来了解⼀下什么是递归?递归(recursion):即程序调⽤⾃⾝的⼀个编程技巧。

⾸先,递归需要满⾜以下2个条件:
1)有反复执⾏的过程(调⽤⾃⾝)
2)有跳出反复执⾏过程的条件(递归出⼝)那递归是不是就是万能的呢?其实不然,递归的有优点当然就有缺点!优点:递归的优点是为某些编程问题提供了最简单的解决⽅案。

缺点:缺点是⼀些递归算法会快速的消耗计算机的内存资源,另外,递归不⽅便阅读和维护。

接下来,我们⽤⼀个例⼦来说明递归的优缺点。

下⾯我们就来看⼏个递归例⼦:
(1)阶乘
(2)汉诺塔问题
(3)全排列
从n个不同元素中任取m(m≤n)个元素,按照⼀定的顺序排列起来,叫做从n个不同元素中取出m个元素的⼀个排列。

当m=n时所有的排列情况叫全排列。

如1,2,3三个元素的全排列为:
(4)斐波那契数列
斐波纳契数列,⼜称黄⾦分割数列,指的是这样⼀个数列:1、1、2、3、5、8、13、21、……这个数列从第三项开始,每⼀项都等于前两项之和。

有趣的兔⼦问题:
⼀般⽽⾔,兔⼦在出⽣两个⽉后,就有繁殖能⼒,⼀对兔⼦每个⽉能⽣出⼀对⼩兔⼦来。

如果所有兔⼦都不死,那么⼀年以后可以繁殖多少对兔⼦?
分析如下:
依次类推可以列出下表:
更多⼲货笔记关注微信公众号 : ⽼九学堂。

c语言函数递归调用

c语言函数递归调用

c语言函数递归调用C语言函数递归调用在C语言中,函数递归调用是一种函数自身调用自身的技术。

通过递归调用,可以解决一些需要重复执行的问题,简化代码逻辑,提高程序的可读性和可维护性。

本文将介绍C语言函数递归调用的基本原理、使用方法以及注意事项。

一、递归调用的原理函数递归调用是基于函数的自身调用,即函数内部直接或间接地调用自己。

当函数执行到递归调用语句时,会暂时中断当前的执行,转而执行被调用的函数,直到满足某个条件才会停止递归,然后逐层返回,继续执行未完成的代码。

二、递归调用的语法在C语言中,通过在函数体内部调用函数本身来实现递归调用。

递归函数通常包含两部分:递归终止条件和递归调用语句。

递归终止条件用于判断是否需要继续递归调用。

当满足终止条件时,递归调用将停止,函数开始逐层返回。

如果没有设置递归终止条件或者终止条件不满足,递归将无限进行下去,导致堆栈溢出。

递归调用语句是实际进行递归的部分。

通过在函数体内部调用函数本身,可以将问题不断地分解为更小的子问题,直到问题被分解为最简单的情况,然后逐层返回结果,最终得到问题的解。

三、递归调用的使用场景函数递归调用在解决一些需要重复执行的问题时非常有用。

以下是一些常见的使用场景:1. 阶乘计算:通过递归调用,可以很方便地计算一个数的阶乘。

例如,计算n的阶乘可以定义一个递归函数factorial(n),其中终止条件是n为1,递归调用语句是return n * factorial(n - 1)。

2. 斐波那契数列:递归调用可以简洁地实现斐波那契数列的计算。

斐波那契数列的定义是前两个数为1,之后的数是前两个数的和。

通过递归调用,可以轻松计算出斐波那契数列的第n个数。

3. 文件路径遍历:在文件系统中,递归调用可以用于遍历文件路径,实现深度优先搜索。

通过递归调用,在遍历一个目录下的所有文件和子目录时,可以方便地遍历子目录中的文件。

四、递归调用的注意事项使用函数递归调用时,需要注意以下事项,以避免出现错误或导致程序异常:1. 设置递归终止条件:在递归函数中,必须设置一个递归终止条件,以确保递归调用会停止。

函数的递归调用

函数的递归调用

函数的递归调⽤
⼀、定义:函数的递归调⽤是函数的嵌套调⽤的⼀种特殊形式,表现为在调⽤⼀个函数的过程中⼜直接或间接地调⽤了⾃⾝,实现了循环,所以说递归的本质就是循环。

def f1():
f1() # ⾃我循环调⽤
def f2():
f3()
def f3():
f2()
# 互相循环调⽤
⼆、递归调⽤实现的循环与while循环的区别:while循环可以通过保持条件永远为真实现⽆限循环,但是每次循环不会额外申请内存空间。

递归调⽤每次都会申请新的局部空间,所以默认有上限次数1000,该次数可以修改。

三、递归调⽤的两个阶段
1、回溯:⼀层层的调⽤直⾄满⾜终⽌条件的过程称为回溯。

2、递推:从满⾜终⽌条件向外层逐层返回的过程称为递推。

def add(n):
if n == 1:
return 100
return add(n - 1) + 1
print(add(6)) # 结果为 105
# add(6) = add(5) + 1
# add(5) = add(4) + 1
# add(4) = add(3) + 1
# add(3) = add(2) + 1
# add(2) = add(1) + 1
# 以上是回溯过程
# add(1) = 100
# add(2) = 100 + 1 = 101
# add(3) = 101 + 1 = 102
# add(4) = 102 + 1 = 103
# add(5) = 103 + 1 = 104
# add(6) = 104 + 1 = 105
# 以上是递推过程。

C语言中的递归调用

C语言中的递归调用

C语言中的递归调用递归:这个词简直是大多数初学者的噩梦,当初学者在接触递归时,简直是一头雾水,很难理解,这是正常的,因为我们都不是天才,主要原因呢还是归功于不理解递归在底层到底发生了什么,而是只看表面,当然就很难明白递归到底是怎么一回事,但当能明白底层发生了什么,基本也就不难理解了。

一、递归的介绍:C语言中的函数都支持递归,递归换句话说就是自己调用自己,递归分为直接调用自己跟间接调用自己,其实只要直接调用自己能理解了,间接调用也就不在话下了。

二、递归的实现:递归之所以能实现,就是因为函数在运行时在栈中都有自己形参和局部变量的副本,而这些副本与该函数的执行过程不发生任何关系,因为这种机制递归才能实现。

举一个大众都知道的,阶乘n!的例子,程序如下:#include<stdio.h>int f(int n){if(n>0)return n*f(n-1);elsereturn 1;}int main(){int mul;scanf('%d',&mul);printf('%d',f(mul));{比如输入的数字为3,当执行递归函数时,数字3被赋给形参n,此时会产生一个形参的副本,数字3会被送到栈中(栈就像一个容器,有先进后出的特性),而后由于3大于0,执行随后的语句:return n*f(n-1)语句,此处为调用点,虽然执行到return语句,但是不会结束,还会继续调用f(n-1),就是f(2),而后形参2,也被送入到栈中,通过f(2)函数里的条件判断语句,依然得到n>0,,继续上面的过程,直到n=0,然后返回1,函数不会在调用自身,自此栈中的数据为:栈顶0,3在最下面,至此就可以逐层返回,因为最后面的return n*f(n-1),并没有执行结束,上面的只不过在逐层调用,此时就开始返回,从栈顶开始,使用它自己的变量,一旦使用过就立即销毁,先得到0,由return 1语句就得到f(0)=1,至此栈中的0就被销毁,然后再返回到上一层,执行f(1)中return f(0)*n,此时栈顶的数值为1(那么n=1),因此f(1)返回1,此时栈顶的1立即被销毁,而后在返回到上一层f(2)中return f(1)*n,此时栈顶的数值为2,那么f(2)返回数值2,栈顶数值2被销毁,依次上面的过程,直到f(3)返回6,最后直到推出,结束递归。

C语言函数的递归和调用

C语言函数的递归和调用

C语⾔函数的递归和调⽤函数记住两点:(1)每个函数运⾏完才会返回调⽤它的函数;每个函数运⾏完才会返回调⽤它的函数,因此,你可以先看看这个函数不⾃我调⽤的条件,也就是fun()中if条件不成⽴的时候,对吧,不成⽴的时候就是N==0的时候,所以返回;(2)还有⼀点就是函数实参传给形参之后,形参的变化是不会改变原实参的值的。

c语⾔函数递归调⽤的问题#include <stdio.h>void fun(int);int main(){int a = 3;fun(a);printf("\n");return 0;}void fun(int n){if(n>0){fun(--n);printf("%d", n);fun(--n);}}解释答案为什么是0120过程分析:先调⽤fun(3),fun(3)中调⽤fun(2),fun(2)中调⽤fun(1),fun(1)中调⽤fun(0),此时n=0,,条件不成⽴,这时开始以⼀层⼀层返回,返回到fun(1),fun(1)中第⼀条调⽤完了(刚返回的),--n此时n=0,输出0,然后接着递归调⽤fun(--n),n已经变成-1,这时fun(1)全执⾏完了,返回到fun(2),,同样fun(2)中第⼀条调⽤完了(刚返回的),--n,此时n=1,输出1,然后接着递归调⽤fun(--n),n已经变成0,,这时fun(2)全执⾏完了,返回到fun(3),,同样fun(3)中第⼀条调⽤完了(刚返回的),--n,此时n=2,输出2,然后接着递归调⽤fun(--n),n已经变成1,,在递归调⽤fun(1)中⼜有⼀次输出0(跟前⾯那次调⽤⼀样),,这时fun(3)全执⾏完了,返回到主函数。

理解C语⾔递归函数的逐级返回(return)2016年07⽉05⽇ 10:28:25阅读数:8110递归函数,也即调⽤⾃⾝的函数。

C Primer Plus中有个例⼦很棒:/*理解C语⾔递归函数*/#include<stdio.h>void up_and_down(int);int main(void){up_and_down(1);return 0;}void up_and_down(int n){printf("level %d: n loacation %p\n", n, &n);/*1*/if (n < 4)up_and_down(n + 1);printf("level %d: n loacation %p\n", n, &n);/*2*/}该段代码中,up_and_down不断调⽤⾃⼰,输出如下结果:相信输出level1、level2、level3、level4,很好理解,但是为什么还会输出level4、level3、level2、level1呢?原来,在第⼀次输出level4之后,函数不再继续调⽤up_and_down()函数,⽽是执⾏return语句,此时第四级调⽤结束,把控制返回给函数的调⽤函数,也就是第三级调⽤函数,第三级调⽤函数中前⼀个执⾏过的语句是在if语句中进⾏第四级调⽤,因此,执⾏其后续的代码,也就是语句#2,这将会输出level3。

函数的递归调用

函数的递归调用递归调用是指一个函数把自己调用自身的方法。

它包括一个终止条件和一个调用自身的指令,由它构成的一种编程技巧。

递归调用有助于我们更有效地解决计算机问题,特别是当这些问题可以递归处理时,它们可以节省空间和时间。

1. 什么是递归调用递归调用是一种编程技巧,它涉及到函数自身调用自身,而且必须包括一个终止条件,即程序能知道自己停止调用自身的条件。

它可以更高效地解决计算机问题,是一种编程实用技巧。

2. 递归调用优势(1)递归调用能够比其它的计算机程序算法更高效地解决问题;(2)它可以保护代码的简洁,从而使其更容易理解和维护;(3)它可以节省空间和时间;(4)它可以实现过滤和模糊匹配。

3. 递归调用的编写递归调用包括一个终止条件和一个调用自身的指令。

编写递归程序有以下三个要点:(1)找到问题的终止条件:首先要找到能够停止调用自身的条件,这个条件被称为终止条件,也称为基层条件;(2)带有变量的编写:递归是将大问题拆解成小问题来求解,所以为了能够拆解出更小的问题,我们必须在编写的时候加上一些变量;(3)调用自身:递归对问题的解法十分重要,即调用函数自身。

当函数取得了问题的更小的部分答案之后,调用自身函数,就可以获得完整的答案。

4. 递归调用的应用(1)实现排序算法:递归调用可以实现许多常见的排序算法,比如快速排序、归并排序等;(2)处理树形结构:递归调用可以非常有效地处理树形结构的数据,例如,深度优先搜索和广度优先搜索;(3)处理数学表达式:可以用递归调用解析并处理复杂的数学表达式,例如,解析逻辑表达式;(4)处理字符串和文本:可以用递归调用处理字符串和文本,例如,过滤HTML标签。

c语言函数递归调用的执行流程

c语言函数递归调用的执行流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。

文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!C 语言函数递归调用的执行流程如下:1. 函数调用:在程序执行过程中,当遇到一个函数调用时,程序会暂停当前函数的执行,并将控制权转移到被调用的函数。

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

C语言中递归函数的教学方法在教授C语言中的递归函数时,我们可以采用以下教学方法:一、引入递归概念和原理首先,我们需要向学生们解释什么是递归以及递归函数的原理。

递归是指一个函数直接或间接地调用自己的过程。

通过一个简单的例子,如计算阶乘,来引导学生理解递归的概念。

然后,解释递归函数的工作原理,即每一次递归调用都会将问题分解为规模更小的子问题,直到达到基本情况(递归停止条件),然后依次返回结果。

二、示范递归调用过程接着,我们可以使用一个实际的例子来示范递归调用的过程,如计算斐波那契数列。

我们可以用具体的数值来展示函数调用栈,以及每次递归调用会如何返回结果。

这样可以帮助学生更直观地理解递归的工作过程。

三、教授递归函数的编写与调用经过前两步的引导,学生们应该可以理解递归函数的原理。

然后,我们可以教授学生如何编写和调用递归函数。

这包括函数的定义、终止条件的判断和处理、递归调用的方法等。

我们可以使用一些简单的示例,如计算阶乘、斐波那契数列、二叉树的遍历等,来让学生们亲自编写递归函数并运行。

同时,我们需要向学生们强调递归函数的设计的重要性,以避免无限递归导致的程序崩溃。

四、递归函数中的陷阱与优化递归函数在编写过程中可能会遇到一些陷阱,例如无限递归、堆栈溢出等问题。

我们需要向学生们提示这些陷阱,并讲解如何避免或解决这些问题。

此外,我们还可以介绍一些递归函数的优化技巧,例如尾递归优化、缓存中间结果、剪枝等,以提高递归函数的效率和性能。

五、扩展应用与实际案例最后,我们可以引导学生们探索更多的递归应用和实际案例。

例如,图的深度优先、回溯法、分治算法等都是基于递归的常见算法。

我们可以通过这些实际案例来巩固学生们对递归函数的理解和运用能力。

同时,我们也可以鼓励学生们尝试自己设计和实现基于递归的算法,以提升他们的创造力和解决问题的能力。

六、练习和总结在教学结束时,我们可以给学生们一些练习题来巩固他们对递归函数的理解和编写能力。

函数的递归调用

函数的递归调⽤⼀:递归的定义函数的递归调⽤:是函数嵌套调⽤的⼀种特殊形式具体是指:在调⽤⼀个函数的过程中⼜直接或者间接地调⽤到本⾝1、直接调⽤本⾝def f1():print('我调我⾃⼰')f1()f1()2、间接调⽤本⾝def f1():print('===>f1')f2()def f2():print('===>f2')f1()f1()如何理解递归:# ⼀段代码的循环运⾏的⽅案有两种⽅式⼀:while、for循环while True:print(1111)print(2222)print(3333)# ⽅式⼆:递归的本质就是循环:def f1():print(1111)print(2222)print(3333)f1()f1()如何结束⼀个递归函数:def f1(n):if n == 10:returnprint(n)n+=1f1(n)f1(0)递归的两个阶段:回溯:⼀层⼀层调⽤下去递推:满⾜某种结束条件,结束递归调⽤,然后⼀层⼀层返回例:某公司四个员⼯坐在⼀起,问第四个⼈薪⽔,他说⽐第三个⼈多1000,问第三个⼈薪⽔,第他说⽐第⼆个⼈多1000,问第⼆个⼈薪⽔,他说⽐第⼀个⼈多1000,最后第⼀⼈说⾃⼰每⽉5000,请问第四个⼈的薪⽔是多少?思路解析:要知道第四个⼈的⽉薪,就必须知道第三个⼈的,第三个⼈的⼜取决于第⼆个⼈的,第⼆个⼈的⼜取决于第⼀个⼈的,⽽且每⼀个员⼯都⽐前⼀个多⼀千,数学表达式即:salary(4)=salary(3)+1000salary(3)=salary(2)+1000salary(2)=salary(1)+1000salary(1)=5000总结为:salary(n)=salary(n-1)+1000 (n>1)salary(1)=5000 (n=1)在回溯阶段,要求第n个员⼯的薪⽔,需要回溯得到(n-1)个员⼯的薪⽔,以此类推,直到得到第⼀个员⼯的薪⽔,此时,salary(1)已知,因⽽不必再向前回溯了。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归(recursive)调用。

C++允许函数的递归调用。

例如:
.int f(int x)
.{
.int y, z;
.z=f(y); //在调用函数f的过程中,又要调用f函数
.return (2*z);
.}
以上是直接调用本函数,见图4.9。

图4.10表示的是间接调用本函数。

在调用f1函数过程中要调用f2函数,而在调用f2函数过程中又要调用f1函数。

图4.9 图4.10 从图上可以看到,这两种递归调用都是无终止的自身调用。

显然,程序中不应出现这种无终止的递归调用,而只应出现有限次数的、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用,否则就不再继续。

包含递归调用的函数称为递归函数。

【例4.10】有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。

问第4个人岁数,他说比第3个人大两岁。

问第3个人,又说比第2个人大两岁。

问第2个人,说比第1个人大两岁。

最后问第1个人,他说是10岁。

请问第5个人多大?每一个人的年龄都比其前1个人的年龄大两岁。

即:age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=10 可以用式子表述如下:
age(n)=10 (n=1) age(n)=age(n-1)+2 (n>1) 可以看到,当n>1时,求第n个人的年龄的公式是相同的。

因此可以用一个函数表示上述关系。

图4.11表示求第5个人年龄的过程。

图4.11
可以写出以下C++程序,其中的age函数用来实现上述递归过程。

.#include <iostream>
.using namespace std;
.int age(int);//函数声明
.int main( )//主函数
.{
.cout<<age(5)<<endl;
.return 0;
.}
.
.int age(int n)//求年龄的递归函数
.{
.int c; //用c作为存放年龄的变量
.if(n==1) c=10; //当n=1时,年龄为10
.else c=age(n-1)+2; //当n>1时,此人年龄是他前一个人的年龄加2
.return c; //将年龄值带回主函数
.}
运行结果如下:18 【例4.11】用递归方法求n!。

求n!可以用递推方法,即从1开始,乘2,再乘3……一直乘到n。

求n!也可以用递归方法,即5!=4!×5,而4!=3!×4,…,1!=1。

可用下面的递归公式表示:n! = 1 (n=0, 1) n * (n-1)! (n>1) 有了例4.10的基础,很容易写出本题的程序:
.#include <iostream>
.using namespace std;
.long fac(int);//函数声明
.int main( )
.{
.int n;//n为需要求阶乘的整数
.long y; //y为存放n!的变量
.cout<<"please input an integer :"; //输入的提示
.cin>>n; //输入n
.y=fac(n);//调用fac函数以求n!
.cout<<n<<"!="<<y<<endl; //输出n!的值
.return 0;
.}
.
.long fac(int n) //递归函数
.{
.long f;
.if(n<0)
.{
.cout<<"n<0,data error!"<<endl; //如果输入负数,报错并以-1作为返回值
.f=-1;
.}
.else if (n==0||n==1) f=1; //0!和1!的值为1
.else f=fac(n-1)*n;//n>1时,进行递归调用
.return f;//将f的值作为函数值返回
.}
运行情况如下:please input an integer:10↙10!=3628800 许多问题既可以用递归方法来处理,也可以用非递归方法来处理。

在实现递归时,在时间和空间上的开销比较大,但符合人们的思路,程序容易理解。

相关文档
最新文档