欢迎阅读个人我的博客,有更好的排版和文章:https://pushy.sitejavascript
一提及递归,我想每一个人都不陌生。举个从小就听过的例子:从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山...java
还有你从两面相对的镜子中看到的画面,其实都是抽象出来的递归现象,可是严格来讲并非递归,由于会一直重复下去,没有终止条件,那就称为死循环了。有关递归和死循环的异同咱们以后会说到,那么如今先来了解一下什么是递归?node
那么什么是递归呢? 要理解递归,就得先了解什么是递归,实际上这句话就是一个递归。这么说可能很差理解,接下来我举个简单的例子来解释这段话的意义。python
假设咱们如今都不知道什么是递归,咱们天然想到打开浏览器:输入到谷歌的网页,点击搜索递归,而后在为维基百科中了解到了递归的基本定义。在了解到了递归其实是和栈有关的时候,你又蒙圈了,什么是栈呢?数据结构没学清楚,此时的你只能又打开谷歌,搜索什么是栈。接下来你依次了解了内存/操做系统。在你基本了解好知识以后,你经过操做系统了解了内存,经过内存了解了栈,经过栈了解了什么是递归这下你恍然大悟!原来这就是递归啊!git
这下应该有点明白了吧,这个过程其实就是递归的过程,若是不了解递归,那就先了解什么是递归,可能你会说这是个循环并非递归,咱们前面说到,递归是须要终止条件的,那么你明白递归是什么其实就是终止条件。整个过程,搜索引擎充当递归函数(只是形象的假设)。在你去依次查找递归/栈/内存/操做系统的过程为前行阶段,在你都了解完以后,反回去了解含义的过程为退回阶段。若是仍是不太清楚,能够接着看下面的例子。github
也许以前你在网络上看到过这张图片:算法
实际上这张图就很形象地表达出了递归,这句吓得我抱起了抱着抱着抱着个人小鲤鱼的个人个人我若是从字面意义上看可能看不出是什么意思,那么咱们能够经过代码来实现一样的效果:浏览器
function Recursion(depth) { console.log('抱着'); if (!depth) { console.log('个人小鲤鱼') } else { Recursion(--depth); // 递归调用 } console.log('的我'); } console.log('吓得我抱起了'); Recursion(2)
在终端的打印结果为以下,能够看到和上面的那段话是同样的:网络
代码其实十分简单,可是须要理解的是:if
代码块的条件(!depth
)为递归调用的终止条件,在else
代码块内递归调用函数.咱们前面有说到递归的过程是存在前行和退回阶段的,那么在前行阶段咱们在每次调用函数后,打印出了"抱着",而且当depth≠0
时从新调用该函数;在退回阶段,将会去执行代码console.log('的我');
再打印出"的我".数据结构
褚跃跃的图也能比较清楚地反映出这个过程:
好了!这下你应该明白什么是递归了吧?若是你尚未明白什么是递归的话,你能够看什么是递归?
有关递归应用的应用有不少,例如注明的斐波拉契数列就能够经过递归来实现:
def fib(x): if x < 2: return 0 if x == 0 else 1 # 当x > 2时,开始递归调用fib()函数: return fib(x - 1) + fib(x - 2) print(fib(6)) # 打印结果为:8
这里须要对i<2
时的特殊状况作出判断,当x==0
时,直接返回0
,当x==1
时,直接返回1
首先咱们须要了解遍历的算法:定义的file_display
函数以某个目录(/home/pushy
)做为遍历的起点.遇到一个子目录时,就先接着遍历子目录(递归调用函数)。遇到一个文件时,就直接对改文件进行操做(这里只打印出文件的文件名):
import os def file_display(filepath): for each in os.listdir(filepath): # 获得文件的绝对路径: absolute_path = os.path.join(filepath, each) # 获得是否为文件仍是目录的布尔值: is_file = os.path.isfile(absolute_path) if is_file: # 当前的绝对路径为文件: print(each) else: # 当前的绝对路径为目录: file_display(absolute_path) file_display('/home/pushy')
这样咱们就能够遍历到/home/pushy
路径下的全部文件:
另外咱们还可使用递归来建立目录:
import os def createFile(dirname): exits = os.path.exists(dirname) if exits: return True else: # 开始递归调用函数,并接受其返回值: rec_result = createFile(os.path.dirname(dirname)) if rec_result: # 若是不存在该目录,则建立dirname的目录,并返回已经建立(存在)的值True: os.mkdir(dirname) return True createFile('./aa/bb/cc')
好了,递归的知识差很少介绍完了。若是看完上边大概已经了解了循环和递归的区别了。对了!简单来讲,循环是有去无回,而递归则是有去有回(由于存在终止条件)。
举个栗子,你用你手中的钥匙打开一扇门,结果去发现前方还有一扇门,紧接着你又用钥匙打开了这扇门,而后你又看到一扇们...可是当你开到某扇门时,发现前方是一堵墙无路可走了,你选择原路返回——这就是递归
可是若是你打开一扇门后,一样发现前方也有一扇们,紧接着你又打开下一扇门...直到打开最后一扇门出去,或者一直没有碰到尽头 (死循环)——这就是循环。
参考资料: