【Python学习之四】递归与尾递归
看完廖雪峰老师的教程,感觉尾递归函数是一个相对难点。于是复习一下,思考了一下,发表一些见解,记录一下。
1、递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 例如,阶乘的实现:f(n) = n! = 1x2x3x4......xn = f(n-1) x n。因此,f(n)用递归函数写出来是:
def f(n):
if n == :
return
return f(n - ) * n
f(5)的计算过程如下:
===> f()
===> * f()
===> * ( * f())
===> * ( * ( * f()))
===> * ( * ( * ( * f())))
===> * ( * ( * ( * )))
===> * ( * ( * ))
===> * ( * )
===> *
===>
递归函数可以把复杂的循环,写成逻辑上容易理解的结构。但是,使用递归函数需要注意防止栈溢出。递归对系统内存的消耗是很大的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。于是,为了解决这个问题,提出了尾递归的概念。
2、尾递归函数
尾递归是指,在函数返回的时候,return语句不能包含表达式(含加减乘除等操作),只能是递归调用。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。下面是一个示例:
def f(n):
return fact_iter(n, 1) # 返回的是另一个递归调用函数的结果 def fact_iter(num, product): # num是想要计算的值,product是结果
if num == 1:
return product
return fact_iter(num - 1, num * product) # 将乘积结果传入函数
比较递归函数和尾递归函数,很明显的是递归函数f(n)中 return f(n - 1) * n 是一个乘法表达式,不是递归调用函数。而fact_iter(num, product)函数则不一样, return fact_iter(num - 1, num * product) 是递归调用。f(5)对应的函数fact_iter(5, 1)计算过程:
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
但是Python解释器没对尾递归做优化。
最后,汉诺塔的移动,使用递归算法,可以实现一下。我的实现如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2018-05-22 16:22:13
# @Author : Chen Jing (cjvaely@foxmail.com)
# @Link : https://github.com/Cjvaely
# @Version : $Id$ # 汉诺塔的移动可以用递归函数非常简单地实现
# 需求:打印出把所有盘子从A借助B移动到C的方法 def move(n, a, b, c):
if n == 1:
print(a, '-->', c)
else:
move(n - 1, a, c, b)
move(1, a, b, c)
move(n - 1, b, a, c) # 期待输出:
# A --> C
# A --> B
# C --> B
# A --> C
# B --> A
# B --> C
# A --> C move(3, 'A', 'B', 'C')
【Python学习之四】递归与尾递归的更多相关文章
- 【Python学习之四】集合类型
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 一.字符串:字符串实际上就是字符的数组1.切片是指 ...
- Python 基础之递归 递归函数 尾递归 斐波那契
1.递归函数 定义:自己调用自己的函数递:去归:回有去有回是递归#(1)简单的递归函数def digui(n): print(n) if n > 0: digui(n- ...
- python学习笔记 | 递归思想
1.引子 大师 L. Peter Deutsch 说过: To Iterate is Human, to Recurse, Divine. 中文译为:人理解迭代,神理解递归 2.什么是递归 简单理解: ...
- Python学习之四【变量】
变量:用于引用(绑定)对象的标识符 语法: >>变量名=对象 (数值,表达式等) 如计算圆的面积 PI=3.14 redius:12.3 area=PI*radius**2(**在pyth ...
- python学习:递归列出目录里的文件
#!/usr/bin/python import os import sys def print_files(path): lsdir = os.listdir(path) d ...
- Python学习笔记———递归遍历多层目录
import os #得到当前目录下所有的文件 def getALLDir(path,sp = ""): filesList = os.listdir(path) #处理每一个文件 ...
- python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程
python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...
- python学习笔记:第14天 内置函数补充和递归
一.匿名函数 匿名函数主要是为了解决一些简单需求而设计的一种函数,匿名函数的语法为: lambda 形参: 返回值 先来看一个例子: # 计算n的n次方 In[2]: lst = lambda n: ...
- Python学习总结之四 -- 这就是Python的字典
字典原来是这么回事儿 Python学习到现在,我们已经知道,如果想将值分组到结构中,并且通过编号对其进行引用,列表就可以派上用场.不过,今天,我们将学到一种通过名字引用值的数据结构,应该知道这种数据类 ...
随机推荐
- JavaScript进阶 - 第7章 JavaScript内置对象
第7章 JavaScript内置对象 7-1 什么是对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的, ...
- 一个VUE的小案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- .NET 基础 一步步 一幕幕[XML基础操作]
XML可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. 什么是XML,学他有什么用? 优点:容易读懂,格式标准任何语言都内置了XML分析引擎,不用单独进行文件分 ...
- mysql 驱动问题
转 : https://blog.csdn.net/bloodycuckoo/article/details/51175339 转 : https://blog.csdn.net/u010746431 ...
- (办公)ssm发送邮件
1.添加jar包 <!-- Javamail API --> <dependency> <groupId>javax.mail</groupId> &l ...
- Kendo MVVM 数据绑定(十) Source
Kendo MVVM 数据绑定(十) Source Source 绑定可以把 ViewModel 的值和由 Kendo 模板定义的目标元素绑定,如果 ViewModel 的值发生变化,被绑定的目标元素 ...
- 【Unity3D】射箭打靶游戏(简单工厂+物理引擎编程)
打靶游戏: 1.靶对象为 5 环,按环计分: 2.箭对象,射中后要插在靶上: 3.游戏仅一轮,无限 trials: 增强要求: 添加一个风向和强度标志,提高难度 游戏成品图: U ...
- SQL Server 2012安装配置(Part1 )
1 安装前准备 安装 SQL Server 2012 服务器及客户端前,需要提前做以下两项准备: SQL Server2012 依赖于.Net Framework 3.5.1 组件.Windows S ...
- windows网络和共享中心“查看基本网络信息并设置连接”为“未知”的解决方案
存在问题“查看基本网络信息并设置连接”为“未知”.如图所示: 解决步骤 运行services.msc 启动Network List Service 若无法启动,打开其属性,选择“登录”选项卡,将启动类 ...
- java面试题(杨晓峰)---第一讲谈谈你对java平台的理解
本人总结: 面向对象(封装,继承,多态) 平台无关性(jvm运行,class文件) 语言(泛型,lambda) 类库(集合,并发,网络,io/nio) jre(java运行环境,JVM,类库) JDK ...