python--递归(附利用栈和队列模拟递归)
博客地址:http://www.cnblogs.com/yudanqu/
一、递归
- 递归调用:一个函数,调用的自身,称为递归调用
- 递归函数:一个可以调用自身的函数称为递归函数
凡是循环能干的事,递归都能干
方法:
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) # 大家想一下,栈是哪里进哪里出,也就是,刚进去的元素,接下来的一次循环又出来了,那便是一条路走到头,是深度遍历;那么现在一头进另一头出是什么意思呢,就是即便判断了这个是一个目录,但我现在不执行你,我要把你前面这些都查一遍,找完是目录的都添加在后面,之后再遍历你们这些,就是把一层的内容找完再找下一层,被称为广度优先遍历。
写这篇随笔的时候没有考虑到也许有些同学还需要学习一下栈和队列,我会在之后再进行一下总结。本人也是初学者,希望和大家一起交流。
作者:渔单渠(yudanqu)
博客地址:http://www.cnblogs.com/yudanqu/
python--递归(附利用栈和队列模拟递归)的更多相关文章
- python之单例模式、栈、队列和有序字典
一.单例模式 import time import threading class Singleton(object): lock = threading.RLock() # 定义一把锁 __inst ...
- Python将列表作为栈和队列
Collections中的各种方法 阅读目录(Content) 一.各种方法介绍 二.代码部分 回到顶部(go to top) 一.各种方法介绍 Counter 统计个数 elements mo ...
- python栈、队列、文件目录遍历
一. 栈与队列 关注公众号"轻松学编程"了解更多. 1. 栈 stack 特点:先进先出[可以抽象成竹筒中的豆子,先进去的后出来] 后来者居上 mystack = [] #压栈[向 ...
- 【LeetCode题解】232_用栈实现队列(Implement-Queue-using-Stacks)
目录 描述 解法一:在一个栈中维持所有元素的出队顺序 思路 入队(push) 出队(pop) 查看队首(peek) 是否为空(empty) Java 实现 Python 实现 解法二:一个栈入,一个栈 ...
- 《剑指offer》递推与循环,栈和队列,回溯 (牛客10.27)
难度 题目 知识点 07. 斐波那契数列 递推递归 - 两变量写法- 08. 跳台阶 同上 09. 变态跳台阶 dp 10. 矩形覆盖 同上 05. 用两个栈实现队列 模拟 ☆ 20. 包含min函数 ...
- 【DataStructure In Python】Python模拟栈和队列
用Python模拟栈和队列主要是利用List,当然也可以使用collection的deque.以下内容为栈: #! /usr/bin/env python # DataStructure Stack ...
- 两队列模拟一个栈,python实现
python实现两个队列模拟一个栈: class Queue(object): def __init__(self): self.stack1=[] self.stack2=[] def enqueu ...
- python 递归深度优先搜索与广度优先搜索算法模拟实现
一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件2.找出这一次和上一次关系3.假设当前 ...
- python数据结构之栈与队列
python数据结构之栈与队列 用list实现堆栈stack 堆栈:后进先出 如何进?用append 如何出?用pop() >>> >>> stack = [3, ...
随机推荐
- linux文件统计命令和目录统计命令
1.统计本目录下除`./apps/myapp/migrations`的所有py文件 wc -l `find -path . -o -name '*py' ! -path "./apps/my ...
- mssql sqlserver 下文分享一种新颖的字符串截取方法
原文地址:http://www.maomao365.com/?p=7307 摘要: 以前分割字符串时,都使用类似split函数的方式处理,下文分享一种对有规律的字符串的分隔方式, 即:1. ...
- wordpress安装后访问博客只显示文字的解决办法
按着网上的教程,买了腾讯云服务器,上面的镜像已经安装好WordPress了.但是发现并不像网上十分钟搭建个人站点等的写的那么简单.遇到了一些问题,下面来详细讲一讲. 首先是用ip地址不能直接访问服务器 ...
- LeetCode算法题-Convert a Number to Hexadecimal(Java实现)
这是悦乐书的第219次更新,第231篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第86题(顺位题号是405).给定一个整数,写一个算法将其转换为十六进制.对于负整数,使 ...
- June 18. 2018, Week 25th. Monday
Health and cheerfulness naturally beget each other. 安康喜乐,相生相成. From Joseph Addison. Good health is a ...
- Spring的AOP基于AspectJ的注解方式开发3
上上偏博客介绍了@Aspect,@Before 上篇博客介绍了spring的AOP开发的注解通知类型:@Before,@AfterThrowing,@After,@AfterReturning,@Ar ...
- Go学习笔记04-函数
目录 函数定义 函数示例 小结 函数定义 函数定义与变量定义相似, func function_name(var1, var2, var3, ...) (return_type1, return_ty ...
- 【NOI2008】志愿者招募
[NOI2008]志愿者招募 和[2017山东day7]养猫做法类似. 都是神仙题. 首先我设\(c_{i,j}=[l[j]\leq i\leq r[j]]\) ,于是就可以列出下面的不等式: \[ ...
- centos7下kubernetes(4.kubernetes组件)
Kubenetes cluster 由master和node组成 Master是kubenetes的大脑.运行着以下进程:kube-apiserver.kube-scheduler.kube-cont ...
- centos7下安装docker(21docker swarm集群创建)
创建swarm集群: 实验环境:盗图 swarm-manager是manager node,swarm-worker1和swarm-worker2是worker node. 所有节点的docker版本 ...