python 利用栈和队列模拟递归的过程


Posted in Python onMay 29, 2018

一、递归

递归调用:一个函数,调用的自身,称为递归调用
递归函数:一个可以调用自身的函数称为递归函数

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

方法:

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

下面我们通过两段代码简单看一下递归和非递归的区别:

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

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

下面看一下通过递归的方法:

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

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

二、递归遍历目录

下面的内容我就通过解释代码来讲解了,如果哪里讲的不清楚,欢迎大家下方评论提意见。

import os # 由于我们遍历目录,所以要找到那个目录并操作,os模块包含普遍的操作系统功能
path = "" # 这是我们要遍历的目录的路径,需要自己写进去
# 既然是递归函数,那么肯定要有个函数,而且这个函数还将在函数内部再次被调用
def getAllDir(path, sp = ''): # 参数中传入路径和sp,这个我最后说一句你就明白了
 # 得到当前目录下的所有文件
 filesList = os.listdir(path) # os.listdir()是os模块下的一个方法,相当于Linux中的ls,查看所有文件
 sp += " " # 这个也先放一下
 # 处理每一个文件
 for fileName in filesList: # 遍历刚才找到的目录下的所有文件
  # 判断是否是目录(要用绝对路径)
  fileAbsPath = os.path.join(path,fileName) # join是os模块下将两个路径拼接在一起的意思,第二个参数不能有斜杠。因为我们要判断一下这个文件是一个普通文件还是一个目录,所有要先把他的绝对路径整理出来
  if os.path.isdir(fileAbsPath): # isdir是判断是否为目录,是则返回True
   print(sp + "目录:", fileName) # 打印当前这个文件,他是个目录
   getAllDir(fileAbsPath,sp = " ") # 这里就开始递归了,因为我们要找到整个目录里的东西,所以当这个文件还是个目录的时候我们需要继续向下找
  else:
   print(sp + "普通文件:", fileName) # 如果仅仅是个普通文件,那么他里面也就没有其他文件了,就可以直接打印他了
getAllDir(path) # 这里是调用函数,让遍历开始
# 最后我来说一下开始写的那个sp,是space的意思,有人也许现在就明白了。那个其实就是让我们方便观察,因为每次打印都是顶行写的,我们分不清他的目录结构,所以通过空格来调整。在函数内部写一个空格增加的表达式,可以使调用次数和空格数相关起来,递归的越深,证明目录的级越低,那么空格越多

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

# 整体思路是没有变得,这里没有写到的也许是重复的,看下上面注释就好了
# 写了一半想起来应该回来写一下栈:栈就是一个容器,但它只有一个口,入栈出栈都从这一个口,而且这个栈很细,进去了就不能颠倒位置了,所以,每入栈一个元素他在最外面时候可以出来,否则得等前面的走完了它才可以出来
import os
def getAllDirDFS(path):
 stack = [] # 这里是用栈来模拟,我们先创建一个列表当做栈
 stack.append(path) # 首先,先向栈里压入路径
 # 处理栈,当栈为空时结束循环(栈为空就说明栈里没有普通文件和目录了,因为我们是每操作一个要把那个取出来)
 while len(stack) != 0:
  # 从栈中取出数据
  dirPath = stack.pop() # pop函数是删除最后一个元素,同时还有一个返回值,就是去除的那个元素,我们再接收一下等等用
  # 目录下所有文件
  filesList = os.listdir(dirPath) # 这个和上面一样
  # 处理每一个文件,如果是普通文件则打印出来,如果是目录则将该目录地址压栈
  for fileName in filesList:
   # print(dirPath)
   fileAbsPath = os.path.join(dirPath,fileName)
   # print(fileAbsPath)
   if os.path.isdir(fileAbsPath):
    # 是目录就压栈
    print("目录:" + fileName)
    stack.append(fileAbsPath) # 当是目录时入栈,它这时就在最外面,下一次循环时候要取出栈的元素是不是还是这个啊,既然是它的话就还有找他内部的东西,等把他找完了才继续找和他并列的那些文件。就是说抓住一根绳子使劲往下找,找到头没有了才返回来,这就是深度优先遍历
   else:
    # 打印普通文件
    print("普通:" + fileName)
getAllDirDFS(path)

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

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

总结

以上所述是小编给大家介绍的python 利用栈和队列模拟递归的过程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python常用小技巧总结
Jun 01 Python
Python+django实现文件上传
Jan 17 Python
python开发之list操作实例分析
Feb 22 Python
Python的Flask框架中的Jinja2模板引擎学习教程
Jun 30 Python
浅谈django model postgres的json字段编码问题
Jan 05 Python
浅谈Python2获取中文文件名的编码问题
Jan 09 Python
对python pandas 画移动平均线的方法详解
Nov 28 Python
Django 反向生成url实例详解
Jul 30 Python
使用python模拟高斯分布例子
Dec 09 Python
python GUI库图形界面开发之PyQt5单选按钮控件QRadioButton详细使用方法与实例
Feb 28 Python
详解Python 中的容器 collections
Aug 17 Python
Python matplotlib可视化之绘制韦恩图
Feb 24 Python
查看django执行的sql语句及消耗时间的两种方法
May 29 #Python
让Django支持Sql Server作后端数据库的方法
May 29 #Python
Django 浅谈根据配置生成SQL语句的问题
May 29 #Python
django表单实现下拉框的示例讲解
May 29 #Python
用python编写第一个IDA插件的实例
May 29 #Python
基于python进行桶排序与基数排序的总结
May 29 #Python
Vue的el-scrollbar实现自定义滚动
May 29 #Python
You might like
PHP4实际应用经验篇(6)
2006/10/09 PHP
在PHP中检查PHP文件是否有语法错误的方法
2009/12/23 PHP
解析mysql 表中的碎片产生原因以及清理
2013/06/22 PHP
PHP从零开始打造自己的MVC框架之类的自动加载实现方法详解
2019/06/03 PHP
JavaScript的parseInt 进制问题
2009/05/07 Javascript
小米公司JavaScript面试题
2014/12/29 Javascript
基于jQuery实现的仿百度首页滑动选项卡效果代码
2015/11/16 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
2017/03/21 jQuery
Bootstrap table学习笔记(2) 前后端分页模糊查询
2017/05/18 Javascript
自定义vue全局组件use使用、vuex的使用详解
2017/06/14 Javascript
纯JS实现只能输入数字的简单代码
2017/06/21 Javascript
JS+HTML5实现获取手机验证码倒计时按钮
2018/08/08 Javascript
微信小程序实现页面跳转传递参数(实体,对象)
2019/08/12 Javascript
解决layer.open后laydate失效的问题
2019/09/06 Javascript
[01:29]2014DOTA2展望TI 剑指西雅图DK战队专访
2014/06/30 DOTA
在Python中使用M2Crypto模块实现AES加密的教程
2015/04/08 Python
Python网络爬虫出现乱码问题的解决方法
2017/01/05 Python
Python 专题六 局部变量、全局变量global、导入模块变量
2017/03/20 Python
python数据结构之链表的实例讲解
2017/07/25 Python
Django 如何获取前端发送的头文件详解(推荐)
2017/08/15 Python
pycharm+django创建一个搜索网页实例代码
2018/01/24 Python
Python实现批量修改图片格式和大小的方法【opencv库与PIL库】
2018/12/03 Python
浅析Python 读取图像文件的性能对比
2019/03/07 Python
Python如何爬取b站热门视频并导入Excel
2020/08/10 Python
python获得命令行输入的参数的两种方式
2020/11/02 Python
css3动画过渡实现鼠标跟随导航效果
2018/02/08 HTML / CSS
利用HTML5 Canvas API绘制矩形的超级攻略
2016/03/21 HTML / CSS
松下电器美国官方商店:Panasonic美国
2016/10/14 全球购物
Rossignol金鸡美国官网:始于1907年法国百年雪具品牌
2019/03/06 全球购物
英国最大的滑板品牌选择:Route One
2019/09/22 全球购物
2015年教学工作总结
2015/04/02 职场文书
新学期主题班会
2015/08/17 职场文书
MySQL之PXC集群搭建的方法步骤
2021/05/25 MySQL
Golang生成Excel文档的方法步骤
2021/06/09 Golang
MySQL系列之八 MySQL服务器变量
2021/07/02 MySQL
MySQL transaction事务安全示例讲解
2022/06/21 MySQL