python--递归(附利用栈和队列模拟递归)

  博客地址:http://www.cnblogs.com/yudanqu/python

 

1、递归

  • 递归调用:一个函数,调用的自身,称为递归调用
  • 递归函数:一个能够调用自身的函数称为递归函数

  凡是循环能干的事,递归都能干app

方法:
一、写出临界条件
二、找这一次和上一次的关系
三、假设当前函数已经能用,调用自身计算上一次的结果再求出本次的结果

  下面咱们经过两段代码简单看一下递归和非递归的区别:函数

    输入一个大于等于1的数,求1到n的和!学习

1 # 普通函数方法
2 
3 def hanshu(n):
4     sum = 0
5     # 循环遍历每个数字,将他们加到一个事先定义好的变量上,直到加完
6     for x in range(1, n+1):
7         sum += x
8     return sum

  下面看一下经过递归的方法:ui

1 # 递归
2 
3 def digui(n):
4     if n == 1:
5         return 1 # 若是n等于1证实已经递归到最后,返回1,这就是上述的临界条件
6     else:
7         return n + digui(n-1) # 当没有达到临界条件时,用n加上对n-1的递归,每次都把n加进去,可是后面依然是使用当下这个递归函数,会再次调用计算n-1,直到递归结束,也就是将从n到1的数所有递归完

  在实际应用中,递归是十分消耗内存的,可是有些事情他很容易去作,很容易理解。下面,就经过一个案例介绍一下递归的用法。spa

 

2、递归遍历目录

  下面的内容我就经过解释代码来说解了,若是哪里讲的不清楚,欢迎你们下方评论提意见。操作系统

 1 import os # 因为咱们遍历目录,因此要找到那个目录并操做,os模块包含广泛的操做系统功能
 2 
 3 path = "" # 这是咱们要遍历的目录的路径,须要本身写进去
 4 
 5 # 既然是递归函数,那么确定要有个函数,并且这个函数还将在函数内部再次被调用
 6 def getAllDir(path, sp = ''): # 参数中传入路径和sp,这个我最后说一句你就明白了
 7     # 获得当前目录下的全部文件
 8     filesList = os.listdir(path) # os.listdir()是os模块下的一个方法,至关于Linux中的ls,查看全部文件
 9 
10     sp += "  " # 这个也先放一下
11     # 处理每个文件
12     for fileName in filesList: # 遍历刚才找到的目录下的全部文件
13         # 判断是不是目录(要用绝对路径)
14         fileAbsPath = os.path.join(path,fileName) # join是os模块下将两个路径拼接在一块儿的意思,第二个参数不能有斜杠。由于咱们要判断一下这个文件是一个普通文件仍是一个目录,全部要先把他的绝对路径整理出来
15         if os.path.isdir(fileAbsPath): # isdir是判断是否为目录,是则返回True
16             print(sp + "目录:", fileName) # 打印当前这个文件,他是个目录
17             getAllDir(fileAbsPath,sp = "  ") # 这里就开始递归了,由于咱们要找到整个目录里的东西,因此当这个文件仍是个目录的时候咱们须要继续向下找
18         else:
19             print(sp + "普通文件:", fileName) # 若是仅仅是个普通文件,那么他里面也就没有其余文件了,就能够直接打印他了
20 
21 
22 getAllDir(path) # 这里是调用函数,让遍历开始
23 
24 # 最后我来讲一下开始写的那个sp,是space的意思,有人也许如今就明白了。那个其实就是让咱们方便观察,由于每次打印都是顶行写的,咱们分不清他的目录结构,因此经过空格来调整。在函数内部写一个空格增长的表达式,可使调用次数和空格数相关起来,递归的越深,证实目录的级越低,那么空格越多

 

3、栈模拟递归遍历目录(深度遍历)

 1 # 总体思路是没有变得,这里没有写到的也许是重复的,看下上面注释就行了
 2 # 写了一半想起来应该回来写一下栈:栈就是一个容器,但它只有一个口,入栈出栈都从这一个口,并且这个栈很细,进去了就不能颠倒位置了,因此,每入栈一个元素他在最外面时候能够出来,不然得等前面的走完了它才能够出来
 3 import os
 4 
 5 def getAllDirDFS(path):
 6     stack = [] # 这里是用栈来模拟,咱们先建立一个列表当作栈
 7     stack.append(path) # 首先,先向栈里压入路径
 8 
 9     # 处理栈,当栈为空时结束循环(栈为空就说明栈里没有普通文件和目录了,由于咱们是每操做一个要把那个取出来)
10     while len(stack) != 0:
11         # 从栈中取出数据
12         dirPath = stack.pop() # pop函数是删除最后一个元素,同时还有一个返回值,就是去除的那个元素,咱们再接收一下等等用
13         # 目录下全部文件
14         filesList = os.listdir(dirPath) # 这个和上面同样
15 
16         # 处理每个文件,若是是普通文件则打印出来,若是是目录则将该目录地址压栈
17         for fileName in filesList:
18             # print(dirPath)
19             fileAbsPath = os.path.join(dirPath,fileName)
20             # print(fileAbsPath)
21             if os.path.isdir(fileAbsPath):
22                 # 是目录就压栈
23                 print("目录:" + fileName)
24                 stack.append(fileAbsPath) # 当是目录时入栈,它这时就在最外面,下一次循环时候要取出栈的元素是否是仍是这个啊,既然是它的话就还有找他内部的东西,等把他找完了才继续找和他并列的那些文件。就是说抓住一根绳子使劲往下找,找到头没有了才返回来,这就是深度优先遍历
25             else:
26                 # 打印普通文件
27                 print("普通:" + fileName)
28 
29 getAllDirDFS(path)

 

 4、队列模拟递归遍历目录(广度遍历)

 1 # 这回记住了,先说一下队列,队是一个两端开口的模型,一头进一头出,固然还有双向队列,循环等等,咱们就简单用一下最基本的队列
 2 
 3 import collections # 队列在python的包里有,因此咱们直接调用一下,不用觉得这个很难,他也只不过是类型是queue,实际的思想是同样的,入队append,由于这个是在右侧,也就是后方入队,另外一边出的话就是popleft,左侧出,是否是很通俗,只是改了一下出来的口
 4 def getAllDirBFS(path):
 5     queue = collections.deque() # 建立一个队列,只要记得后面用法就是上面我说的那个不一样就能够了
 6     queue.append(path)
 7 
 8     while len(queue) != 0:
 9         dirPath = queue.popleft() # 仅仅这里不一样,由于队列模拟是另外一端出队
10         filesList = os.listdir(dirPath)
11         for fileName in filesList:
12             fileAbsPath = os.path.join(dirPath,fileName)
13             if os.path.isdir(fileAbsPath):
14                 print('目录:' + fileName)
15                 queue.append(fileAbsPath)
16             else:
17                 print('文件:' + fileName)
18 
19 getAllDirBFS(path)        
20 
21 # 你们想一下,栈是哪里进哪里出,也就是,刚进去的元素,接下来的一次循环又出来了,那即是一条路走到头,是深度遍历;那么如今一头进另外一头出是什么意思呢,就是即使判断了这个是一个目录,但我如今不执行你,我要把你前面这些都查一遍,找完是目录的都添加在后面,以后再遍历大家这些,就是把一层的内容找完再找下一层,被称为广度优先遍历。    

 

  写这篇随笔的时候没有考虑到也许有些同窗还须要学习一下栈和队列,我会在以后再进行一下总结。本人也是初学者,但愿和你们一块儿交流。code

 

 

  做者:渔单渠(yudanqu)blog

  博客地址:http://www.cnblogs.com/yudanqu/递归

相关文章
相关标签/搜索