看完廖雪峰老师的教程,感觉尾递归函数是一个相对难点。于是复习一下,思考了一下,发表一些见解,记录一下。

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学习之四】递归与尾递归的更多相关文章

  1. 【Python学习之四】集合类型

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 一.字符串:字符串实际上就是字符的数组1.切片是指 ...

  2. Python 基础之递归 递归函数 尾递归 斐波那契

    1.递归函数 定义:自己调用自己的函数递:去归:回有去有回是递归#(1)简单的递归函数def digui(n):    print(n)    if n > 0:        digui(n- ...

  3. python学习笔记 | 递归思想

    1.引子 大师 L. Peter Deutsch 说过: To Iterate is Human, to Recurse, Divine. 中文译为:人理解迭代,神理解递归 2.什么是递归 简单理解: ...

  4. Python学习之四【变量】

    变量:用于引用(绑定)对象的标识符 语法: >>变量名=对象 (数值,表达式等) 如计算圆的面积 PI=3.14 redius:12.3 area=PI*radius**2(**在pyth ...

  5. python学习:递归列出目录里的文件

    #!/usr/bin/python   import os import sys   def print_files(path):     lsdir = os.listdir(path)     d ...

  6. Python学习笔记———递归遍历多层目录

    import os #得到当前目录下所有的文件 def getALLDir(path,sp = ""): filesList = os.listdir(path) #处理每一个文件 ...

  7. python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程

    python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...

  8. python学习笔记:第14天 内置函数补充和递归

    一.匿名函数 匿名函数主要是为了解决一些简单需求而设计的一种函数,匿名函数的语法为: lambda 形参: 返回值 先来看一个例子: # 计算n的n次方 In[2]: lst = lambda n: ...

  9. Python学习总结之四 -- 这就是Python的字典

    字典原来是这么回事儿 Python学习到现在,我们已经知道,如果想将值分组到结构中,并且通过编号对其进行引用,列表就可以派上用场.不过,今天,我们将学到一种通过名字引用值的数据结构,应该知道这种数据类 ...

随机推荐

  1. JavaScript进阶 - 第7章 JavaScript内置对象

    第7章 JavaScript内置对象 7-1 什么是对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的, ...

  2. 一个VUE的小案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. .NET 基础 一步步 一幕幕[XML基础操作]

    XML可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. 什么是XML,学他有什么用? 优点:容易读懂,格式标准任何语言都内置了XML分析引擎,不用单独进行文件分 ...

  4. mysql 驱动问题

    转 : https://blog.csdn.net/bloodycuckoo/article/details/51175339 转 : https://blog.csdn.net/u010746431 ...

  5. (办公)ssm发送邮件

    1.添加jar包 <!-- Javamail API --> <dependency> <groupId>javax.mail</groupId> &l ...

  6. Kendo MVVM 数据绑定(十) Source

    Kendo MVVM 数据绑定(十) Source Source 绑定可以把 ViewModel 的值和由 Kendo 模板定义的目标元素绑定,如果 ViewModel 的值发生变化,被绑定的目标元素 ...

  7. 【Unity3D】射箭打靶游戏(简单工厂+物理引擎编程)

    打靶游戏:     1.靶对象为 5 环,按环计分:    2.箭对象,射中后要插在靶上:    3.游戏仅一轮,无限 trials: 增强要求:  添加一个风向和强度标志,提高难度 游戏成品图: U ...

  8. SQL Server 2012安装配置(Part1 )

    1 安装前准备 安装 SQL Server 2012 服务器及客户端前,需要提前做以下两项准备: SQL Server2012 依赖于.Net Framework 3.5.1 组件.Windows S ...

  9. windows网络和共享中心“查看基本网络信息并设置连接”为“未知”的解决方案

    存在问题“查看基本网络信息并设置连接”为“未知”.如图所示: 解决步骤 运行services.msc 启动Network List Service 若无法启动,打开其属性,选择“登录”选项卡,将启动类 ...

  10. java面试题(杨晓峰)---第一讲谈谈你对java平台的理解

    本人总结: 面向对象(封装,继承,多态) 平台无关性(jvm运行,class文件) 语言(泛型,lambda) 类库(集合,并发,网络,io/nio) jre(java运行环境,JVM,类库) JDK ...