00:00
好了各位,我们下面呢,来探讨一下函数的递归调用,递归调用OK,那函数的递归调用呢,也是我们在学,呃,这个函数调用的时候啊,一个非常重要的内容,尤其是后面,如果同学们在学的时候呢,会学到一些数据结构。在数据结构里面呢,递归就是一个特别重要的知识,那么我们来看看递归调用是一个什么样内容,我们先来看一个基本介绍。什么叫递归调用呢?就是一个函数在函数体内。就是说它在函数体内调用了本身。调用的本身我们就称为递归调用。同学们看一个例子,我们来一个看一个递归调用的快速入门,大家看这里有个案例。大家看这里有个案例,这有一个test函数,看到没有?同学注意看观察,这有一个态函数。Test单数。那这个test函数呢,同学们看到它在这个地方又调用了一个,那也就是说它在函数test函数里边又调用了test。
01:11
这个我们就称之为地位调用。如果它是在函数内调用了别的函数,这个好理解,调用自己呢,你会突然发现,诶有点转不过来了,是这意思吧。说是这样子的,你再看这个函数TEST2,它在这方呢也掉,诶这个我应该是个二啊,这方这是个二,我写错了,待会我们再看一下TEST2。那么我们来看一下同学们,所以我们看一下就是如果说我在这个函数里边,我传了一个TEST4,请同学们思考。同学们思考就是,如果我在这方传了一个调用test的是,请问这一段代码。它会输出什么内容?如果我在这个函数里边调用了test2.4。啊,2.4,那么这个又输出什么函数,当然这个地方同学们注意啊,这个地方呃,要改成TEST2才是递归调用,待会我把它改一下就行了。
02:05
啊,同学们想一想,你们先看第一个题,你们觉得输出什么?如果同学们现在正在听视频的呢,你可以暂停一下视频,先思考一下这个问题。OK,好。现在呢,老师来做一个点评,来做一个点评来吧,我们先把这一段关于函数的递归调用呢,先放在笔记里边去,我们来分享一下这个问题。分析一下这个问题。函数。的递归调用。递归调用。函数递归调用,那我们来看看这里面的内容是有哪些需要给同学们介绍。OK。给他拿一个标题二就行。然后呢,把这一部分内容先把它板书到这里,我们先看一个基本介绍。
03:05
我们先看一个B基本介绍,这个基本介绍说的比较简单哈,就是函数,就说函数体内。调用了本身。我们就将其称为递归调用,能理解,然后呢,这有一个函数递归调用的快速入门案例。来标题三,我们来一起看看案例,来走一段代码。我们来代码说明,打开我们的Vs code,那因为是函数的递归调用呢,我新建一个文件夹。Function DEMO。零三。OK,新建一个文件,Man go。然后package一下啊,Package面包,然后呃,然后呢,我们引入一下format。这个包。
04:00
然后给他一个主函数。好,那现在呢,我们来看一段代码看一段。看。一段。代码。好,这段代码呢,非常的简单啊,非常简单,这有一个函数叫test。它可以接收一个整数。OK,然后呢,我在这里面有一段代码是这样写的,如果N大于二。如果N大于二,就N减减,然后呢。N减减,然后呢,Test。N,然后我在这地方输出了一句话。PTPTLN,然后呢,我输出的是N等于N。好,我在这里调用的时候是这样调用的,各位朋友test什么呢是。现在我想请问输出什么内容?
05:02
来,同学们想一想呢?各位现在还是老规矩,老师呢,把这段代码放在我们的Excel表里面去进行一个分析,分析完了过后,我们看看输出的结果跟我们分分析的结果是否相同,就从而来证明我们对递归调用的理解是否一样啊,来通过分析。通过分析来看一下,来看一下递归,递归调用的特点。OK,来吧,现在呢,老师把这段代码。我把这段代码放到我们的笔记里面来啊,放到我们的Excel表,注意听讲。来跟上思路啊,同学们。我在这儿放了一下。然后呢,同学们还是老规矩,这边是我们的终端输出。中专。输出这个地方仍然是我们的内存。
06:02
这块还是我们的内存。OK,内存没问题吧,嗯,那么内存因为我们这只涉及到站,所以说老师在画的时候呢,就稍微画的简单一点,就直接就画一个站就可以了啊像堆像这块,这个堆区还有代码区,我就暂时不画了,因为我的空间比较有限,我就直接写个站区。具体讲战区。OK,那因为这块呢,因为这个空间会比较大一点,所以说我把这个往上面拿一下。好,来吧,现在我们开始分析,首先代码呢,就从这里开始执行,从主函数开始执行,没问题吧,从主函数开始执行,那主函数一开一一执行呢,就会在这里开辟一个主站。你,你可认为为你可以认为在这个战区里面为我们的主函数开辟了一个空间,能理解吗?主啊,姑且把它叫主站吧,主空间也可以啊,刚才我也讲过这个东西了,它在这里面调用了什么呢?调用了一个函数叫test。
07:07
最听讲test是。没问题吧,大家想一想,根据前面老师讲的规则,当我们的这个嗯,这个程序去调用一个函数时。根据我们前面学习的底层的原理,那么这个时候就会开辟一个新的空间,对不对?新的空间好,新的空间我们就把它画出来。好,这个新的空间我们画在上面去,因为站呢,它是呃,站的规则是先入后出,所以说呢,这个放在上面了,那这地方假设是我们的一个站叫test。好的。那么同学想一想啊,当他调这个T的时候,我们的代码就进从这从这啪掉到这里面去了。是吧,到了这里面去过后呢,同学们看到这有个N,于是在这个站里面呢,我们有个N等于几同学们。
08:01
同学们,你这方是是不是四穿进去的,所以这方N也等于四,这个跟我们以前分析是一样的,现在的情况是这样子啊,同学们,就是你这个地方调用它了。OK,我画一个小图在这里。掉它掉到这来了,那么N等于四过后,下面进到这个语句里面进行判断,请问if if语句大不?现在注意看啊。现在执行到这的时候,这这地方就执行这里面代码嘛,对吧,N大于二吗?N大不大于二,现在N等于四,显然同学们显然。N是大于二的,于是它进到这里面来,就N减减,N减减过后,请问这个四变成解变成三。变成三过后,它又执行了一个test,好注意啊,这个地方开始执行了这个这句话了,就是1NN大于二。N大于二的时候,里面有个if语句。
09:03
这个if里面呢,它执行了一个test。结,因为你这个是刚才N减减了,到这个地方是应该变成三。注意听这后面还有个else语,呃,没有else啊,注意听下面还有一个这个打印语句,我写到这了,现在执行到这了。是不是执行到TEST3了,执行到TEST3,根据我们以前的规则,它继续开辟一个新站。新的独立空间啊,在这个站里面开一个新的独立空间。好,这个新的独立空间呢,还是这样子,到这这里面呢,同学们想。同学们想一想,此时此刻。诶,我把这个再往面放大一点啊,因为这个空间不够大。好,这个也放大一点,此时此刻你这个N。NT3的时候掉到这里面去,这个里面的N就应该是二。也就是说相当于说在这个地方调用了一个它。
10:03
能理解吗?没问题吧,调用它了,好这个时候在这个站里面注意啊,当在这个地方的时候,这个代码就下面代码先先不执行了,他先去执行上面这个站的里面的内容,同样到这一站里面呢,它也有if语句N大于二。各位同学请看啊,这个时候N大于二还成立吗?不成立了,为什么不成立呢?因为你N本身就传进是等于二的,哎,等于三啊,刚才同学们老师说错了,刚才是三啊对对对,是三啊,不好意思,三对是三,三进到这里面去。进到这个里面去,因为空间的关系,我就我就写到一行了啊,因为空间的关系,我就写到一行了,那这个时候N。等于N不等于三呀。我想想啊。哦对对对,是这样子的,你这你这你这传接是个三,所以说它这也是个三,三的话,进到N大于二等于三是成立的,然后执行一个什么呢?他到这里面去执行它这个函数里面的,这个函数里面的N减减。
11:08
这个函数里面N减减呢?好的时刻N减减过后,同学们想。在这个地方。执行在这个里面执行那个N减减,N减减完了过后,这个就变成几了。是不是变成二了,变成二过后,同学们看这边它又去调用了一个test。二因为你这走走到这的时候,这个test就是这个里面的N了吗?好注意啊,下面还有一句话没有没有执行。下面这句话还等待执行,于是到这个TEST3的时候呢,他还没有执行这句话的时候,又开辟一个新的站。啊,又开辟一个新的独立空间,你可以认为是一个站也可以啊,新站去到这里面去了。又是一个新的独立空间来。到上面。到这个独立空间的时候,同学们想到,因为这是二,所以说这传进来呢,仍然是二,对吧,传进来这个地方就是二了。
12:07
好,同学们看到。因为你这传接的就是二,它这个传接这个N就是二,此时此刻这个N大于二已经不成立了,在这个站里边,大家看在这个这个空间里边。啊,那么这个时候N已经不大于二了,对吧,N不大于二了。这个时候大家看N不大于二,所以它就直接执行这个format里面的输出语句,这个里面会输出什么内容,大家看。它是不是会输出N等于多少,那么这个时候在这个站里面,这个N等于多少呢?大家看一下是不是N等于二啊,所以说在这呢,马上就会输出一个N等于二,那么当这个地方输出N等于二过后,这个整个这里面这个独立空间或者叫做站,也可以叫做test的这个里面这个这个test的战呢,就执行完毕了,执行完毕他就返回来。
13:01
它执行完了过后,这个函数啊,就执行完毕了,它返回到哪呢?同学们看它会返回到这来。能理解吗?它会返回到这个地方返回这因为你这你是从这调进去的吗?你本身就是从这开始执行调调用的时候才开辟的这个新的这个test的站。是不是,所以他又回来,回来的时候这个站就消失了。没有了,好,但是这个线已经没有了。这个时候他回到这个地方以后,那么下面这个111句还执行吗?同学们。就是下面,因为它已经进到这个if语句里面了,所以它执行完了过后他又出来了,出来就执行,这里面的话能理解吗?这个时候这里面就会输出一个N等于几呢?大家看这个时候的N是等于还是等于二的。是不是还是等于二,所以说它仍然输出二,输出完了过后这个站。这个站就执行完毕了,执行完毕过后他又回到哪里了呢?
14:02
同样他才这个地方自行完毕,它又回到这个TEST3。能理解吗?他一回来过,当然这个地方就消失了,销毁这个也就没有了,这条线也就没有了。能理解吗?好,这个也没有logo,它又回到这,它回到这个地方了啊,回到这个地方执行,因为它这个调用完毕,执行到这儿,然后又开始执行下面这一句话,因为if执行完了吗?他又执行这里面话这个地方这句话呢,是N等于几呢。同学们想想,是不是N等于三呢?因为这个是不是还保保留个三,这个值在这,所以说它是N等于三,N等于三完了过后,好这个站也就没有了,这个站已经没有了,好最后就回到这个T的四了,Test的四,到此到此这个test就全部执行完毕,执行完毕过后,这个站也就没有了,因此这里面的结果应该是N等于二等于二等于三,就223。大家看这个结果能理解吗?好朋友们,我们来执行一把运行。
15:00
我们可以看到这句话,啊,啊,我们要退出去,重新进入到我们刚才写的代码里边去,来吧,Go wrong。main.go执行。同学们可以看到我们输出的结果是,诶,大家看我这个为什么没输出结果呢?这个没有输出结果是什么原因,我看看啊单FUNCTION03。FUNCTION03,我们看看为什么原因啊,同学们看一下,稍等片刻。好,同学们,我们再来看一下啊,刚才这个代码没有任何问题,我后面发现是因为我们我们没有保存这段代码啊,我们没有保存这段代码就写完了,过后没有保存,来同学再来执行一下,还是刚才那句话,走。同学们看效果,现在执行的是223。跟老师分析的结果完全一致,223,好同学们,刚才老师的这个分析的这个流程特别的重要,我们把它重新撤回去。
16:05
将留留留在这个地方,大家利于大家的这个分析啊,利于大家分析。好,我把这个呢。把这个图整个执行的流程给大家放到这里来。好,大家看清楚了,就这样一个流程,就是说这执行完了过后呢,他在这执行完毕过后,他又回到这来了。对吧,好,这边这个执行完毕过后呢。这这执行完了。过后,同学们。他在这执行完毕过后,然后呢,这个话执行完毕回到这来,同样下面这个站呢,也是把这个输出完了过后,又重新回到了TEST4。最后整个站,所以你看这个流程是从这儿进去,进去。再从这,哎,这我我还少少画了一根线啊,因为在这他还要重新来到这里来,是这意思吧。好,大家看这个流程调一次掉这儿掉这执行完,执行完毕过后这儿回来,回到这儿,哎,回到回到这儿,回到这儿过后,这地方执行完毕又回到这儿,回到这儿过后呢,他把这个执行完毕,又回到TEST3,整个执行完毕流程输出的结果是N等于二,第二个是N等于二,第三个是N等于三,分析完毕。
17:21
分析完毕,大家看能理解吗?好,我把这个示意图给同学们整理到笔记里面去。好,刚才快速入门的代码。代码一我们把写整理一下代码一案例一吧。都可以,我把稍微的整理一下啊,这是第一个案例,还有一个代码二,代码二我们还没写对吧,先把代码一整理一下,刚才我们这段代码是这样子的。来,走一个吧,放这儿。好,我们把它整理到笔记里面,那么这对这一段代码的,对这一段代码的这个,呃,分析图我们写到这。
18:03
上面代码的分析图我们也放到笔记里面去,哪一块是我们的分析图呢?就是这块。对吧。哎,针对这段代码我们做了一个分析。放到笔记里面去,大家看理解了没有?好,这是我们的第一段代码,我们再来看第二一段代码,大家看一看,同学们真的听懂了没有,就说我举两个例子,第一个案例呢,是一个初步入门,第二个案例我看同学们能不能真正的理解,来我们再写一段代码,这段代码就在上面代码做一个微微的调整来看来同学们我把这段代码。写成TEST2,看清楚哦。态心态二,唯一我就改变了一个位置。我就改变了一个位置,叫else。我就改变了一个S,其他我没有做任何的变化。
19:00
我现在请同学们思考一个问题。如果说我把这段代码的调用改成了这样一个形式,请同学们思考一下输出结果。是什么?你再看一眼,诶说老师上面这段代码是调的test,现在这段代码调的是TEST2,好像没有什么变化呀,但是你看我这有S了。同学们思考一下会输出什么?会输出什么?其实这地方就是考考考考验大家有没有真正把这一个函数的调用真的搞明白。其实就是考察这么一点来同学们分析,同学们分析,其实这个站我仍然可以用。仍然可以用,所以说我刚才把它保留起来,我是有目的的,不然我还重新画一遍,太浪费我的时间了。来吧,来同学们看,现在我们把这个地方去掉,把这个拿过来。来,跟上思路。
20:00
看老师如何给你们分析。把这段代码呢,也放在我们的笔记里面来。看清楚了,各位同学。我把它整理到这里。然后呢,我说一下这块应该是怎么操作,请看这。老规矩啊,跟上思路,走到这儿的时候呢,还是掉第一个站命战,只是我把这个改成二。这帮是不是也改他还是泰式二战了,泰史二战过后。这个地方传进来,第一次进来。是不是这个仍然是传传的是一个四啊。是不是一个四。肯定是传四嘛,大家看你这是四,我这传的是四,传一个四过来,N大大于二,大大不大于二,N肯定大于二,于是就进到这个里面去,它这里面不是第一句话是N减减吗。我这我这块因为空间的关系,我就没有写那么多了啊,因为我再写个再换一行我就看不到这个东西了,所以说我写到一行的这种写法,大家看一下不是对的啊,但是呃,我我把这个意思给你们说说清楚,这执行的N减减,N减减过后,同学们思考是不是本站的这个就变成三了。
21:11
是不是,当然这上面这现在还没有,上面还没有啊,只是我不想再重新画一遍了,我先把它暂时放在这儿,能理解好这个地方呢,执行完毕,这个。太子山上过,他在这个地方把山传进去了,传到这这方应该是山。这边是三的话,N大于二成不成立。显然三大于二成立,于是它又N减减这部变成了T,又回到这,这变成二了,这变成二了,勾这个N。大家看N大于二吗?N显然不大于二,于是这里面去执行它的这个else语句。但是非常的遗憾,同学们看到,因为这个里面是if else的判断,因此你已经进到这个if语句了,是不是因为你在这个站里面进入到一一句。
22:02
哎,不不对。啊,不对啊,我们看看这个地方传的是二,传的是二对对对,注意听啊,这个是test的二,传进去是二对不对,传进是二,所以它是2N大于二是不成立的,于是他执行这个else,因此在这个站里面。就是大家看到这个站。在老师重新标一个别的颜色吧,好不好?是不是在这个灰色的这一部分,它会输出一个N等于二。这个没有毛病吧。这个没有毛病,因为你N就是等于二二不大于二,所以它输出else这个地方代码是不是仍然也是else啊,也是else。它执行完毕过后,是不是这个也销毁了,这个就没有了,没有了吧,没有我现在先不把它去掉啊,那么这个时候进入到这个else语句,那么这个else语句。还会执行吗?显然因为你刚才进去的时候是从这个if里面进去的,因此这句话是不会输出的,所以说这个这个相当于什么都没有输出,直接就走了,同样这个地方也是从if里面进去,于是它这里面这个else呢,也是不会执行的,因为它是else的关系,所以这地方也没有任何输出。
23:17
没有输出,相当于说这直接L就走过了,直接回到这儿来,所以说最后结果只有一个N等于二。说你看完全不一样。因为你的语法发生了变化,你的结构是if else结构,所以说你在这个地方,其实只有最上面这个站它执行到这个else了,其他的站在退回的时候,因为它执行了if,那么else这个分支就不执行,因此这个地方会输出一个。就是说白了吧,就是这个地方会输出一个二这方什么都不会输出,什么都没有输出这个,也是什么都没输出这个,当然下面这个呢,也是一样,什么都没输出。最后结果就是N等于二,没有别的东西了,同学们看一下,你能分析出来这个结果不?
24:02
你能分析出来这个结果不?好,我们来执行一下,看看老师分析的对还是不对。来,我把它保存一下先。咨询一下走人。我们可以看到结果是N等于二,没有别的。可以看效果。是不是跟老师分析的是不是完全一样?同学们好,那关于这个递归的调用呢?我们其实通过这两个案例就已经对它有一个认识了,我把笔记给同学们放入进来。好,我把笔记给同学们放到这里来,走着。这是我们的第二一个案例。放好。对吧,放好到位。然后呢,分析的示意图,我们也给大家拿过来,对。对,上面。对上面代码分析的示意图。我把它呢,也给同学们拿过来,注意听啊,我再说一遍,再说一遍,这个执行到这里面的时候,它返回的时候,这个就没有了。
25:08
执行到这个地方返回的时候,这个也就没有了。实际到这个地方返回的时候也没有了,但是我为什么把这个图给你保留下来呢?保留下来的目的就是希望同学们能能够看到这个流程是什么样子的,再说一遍啊,我保留下来是这个图本身,它是返回的时候就是有这个线,返回的时候这个站其实就已经被销毁了。但是因为我想让大家看到这个来龙去脉,所以说我就没有删除明白我的意思吧。好,这个图呢,我也给同学们放到笔记中。这里面唯一的区别跟原先唯一的区别就是因为在这里它的语法是else的结构。Else的结构。IFS,那其实也就是最上面这个站,它直接进入到S了这个站。就老师说说的这个站,因为它进入到if分支,那么else它就不执行,同样这个也是因为它是从if里面调用,上面调用这个test对吧,所以说它也是这样子过来的啊,它也是这样子过来的啊,这个图还有一点小问题,这边应该全部都改成二。
26:13
是吧,都改成二这样子才是跟这边完全匹配的,对吧,这样才是完全匹配的,好的,我把这个分析图呢,应该同学们拿到笔记里面去。方便同学们。以后对他的。一个学习和复习。再看这里啊。OK。好,说白了就是这里面这个地方,说白了就是这个地方输出了一个二,其他没有没有输出这个,这个暂时没有输出的。这个没有输出。这个地方的战呢,其实也没有输出。对不对。这个站也没有输出。没有输出。当然这个地方更没有了,因为它是直接调TEST2对吧,它没有什么输出,这个地方输出了一个二,其实就是这个这个站里面输出一个二。对吧,这输出了二这个站。
27:01
这个占中。再输出二。好,最后结果就是二。好,同学们,我把这个分析呢拿到笔记里面了。好了。好,这是我们这一段代两段代码的分析,那么现在呢,我对递归做一个总结。递归。递归调用的总结,注意听讲。总结,OK,来,我总结四句话。我总结四句话给同学们看一下。好,我们来一个标题三。对吧。嗯,那么我们这个递归调用有哪些需要同学们注意呢?我这里总结了四句话,大家来看一下。第一句话。函数递归调用需要遵守的重要原则,第一个,执行一个函数时,就会创建一个新的受保护的独立空间,也就是我们可以理解成是一个新的函数站,比如说刚才画的这个图T2。
28:03
这个那这个应该它是二啊,刚才这个,哎,这边也也都是它是二战啊,它始二战就说它每调用一次函数,这个面会产生一个新的空间,你可以理解成是一个新的函数站,因为他们之间的数据是完全独立的,他们要执行的代码也是完全独立的,能理解吗?好,这是这就是老师总结的第一句话,第二句话,函数的局部变量是独立的,互相不受影响,不会相互影响,你比如说刚才老师画的一个图,这有一个N。他的名字叫N,哎,我上面这个也叫N,我上面这个站还叫N,没毛病。没毛病,因为他们是互相互独立的,不要认为他们是同一个啊,不要认为他们是同一个,他们名字虽然相同,但是因为他们数据空间是独立的,因此他们的这个变量其实每一个站里面都有一个独立的,完全不一样的,只是它的名字刚好都叫N。能理解吗?这是老师说的第二点,第三点,递归必须向退出递归的条件并际,否则就是一个无限循环,变成一个死归了。
29:08
这个怎么理解呢?同学们看我的代码,同学们看在我的代码里边,我有一个N减减,这个特别的重要,如果说我把这个代码去掉,同学们思考一下,我们会出现一个什么情况。如果我们把这个N减减去掉,那就意味着T的是进去过后N大于二成立,就掉这个TEST2 test2又去掉,他发现N大于二又掉,是不是就一直死在这里面出不来了呀。为什么呢?因为你这个N永远都是都是四,他永远都大于二,于是他就不停的往里面跑,跑跑跑跑跑跑死在里面了。成了一个死,死成了一个无限的调用。这就是死威,因此这个条件是特别重要的,这个条件就是刚才老师所说的递归。递归。必须向。向什么呢?向退出递归。
30:02
递归条件逼近。条件逼近。毕竟。啊。逼近。否则。否则就是循无限循环调用,否则就是无限循环调用。这个就很可怕了啊,因为你那你就永远出不来了。永永远都出不来了,这个调写错了。这个啊,调用能能理解这意思吧,你不然的话永远都永远都出不来。当然你这也不能写成N加加,N加加的更可怕,它永远都是大于二的,也也出不来,这个地方也是特别重要的一点,还有就是第三第四一点,当一个函数执行完毕或者遇到return时,就会返回遵守谁。遵守,谁调用就将结果返回给谁。就是哪一个人调用,我就把这个结果返回给谁,那么这个呢,我在前面已经阐述过这个东西了,同时当他返回的时候,这个函数自身也被销毁,我再把这句话加加进去,当时同时啊,同时当函数返回时,或者执行执行完毕完毕。
31:15
或者。或者返回时。或者啊。或者返回时该函数。该函数本身。该函数本身也被销毁了,本身也会也会被销毁。被谁销毁呢?你可认为是被编译器销毁的,你也可以认为是被系统销毁的,这个无所谓,我就写个系统吧,啊,被系统销毁。就这个战斗空间就释放出来了。所以这四点特别的重要,希望同学们引起这个重视啊,好,我把这四点呢,总结放在我们的笔记里面去。对吧,哎。好的,我把这个稍微的整理一下,第一点板书一下,老师在板书的时候呢,你也多琢磨琢磨啊。
32:05
第二点第三点好了,一共四点,一共四点啊,一共四点,好这诶这个地方没问题,这就是我们关于递归调用的一个说明和介绍,那下面呢,我们就来做一些关于递归调用的。案例和课堂练习,加深对定规调用的理解。那关于地柜的调用,我们先给大家介绍到这里。
我来说两句