1.学习目标

递归函数是直接调用自己或通过一系列语句间接调用自己的函数。递归在程序设计有着举足轻重的作用,在很多情况下,借助递归可以优雅的解决问题。虽然使用递归可以快速的解决一些难题,但由于递归的抽象性,使递归难以掌握。为了更好的理解递归函数背后的思想,本节主要通过可视化方式来了解递归函数的执行步骤。

通过本节学习,应掌握以下内容:

提高对递归的理解

利用可视化理解递归函数背后的思想

2.递归的调用

虽然使用递归可以快速的解决一些难题,但由于递归的抽象性,使得递归难以掌握。虽然已经在《递归基础》中讲解了递归的示例,并且简单的了解了递归的调用过程,但缺乏具体的认知。本节将对递归的调用进行更加深入的讲解。

递归函数执行时,每次递归调用都会在内存中创建新的函数副本,一旦函数调用结束,则返回一些数据,并将此副本就会从内存中删除。通常,递归方法得到的解决方案看起来十分简洁简单,但理解并跟踪函数的执行却较为复杂。为了更好地理解,考虑以下求取斐波那契数列的简单示例:

def fibo(n):
    if n == 0:
        return 1
    else:
        return n * fibo(n - 1)
def main():
    number = 4
    result = fibo(number)
    print(result)
if __name__ == "__main__":
    main()

当程序运行到第 10 行时。第一次调用 fibo() 函数,会为 fibo() 函数调用创建一条新的活动记录,此时在运行时栈上具有 3 条活动记录。然后 Python 解释器跳转到第 2 行,其中 n 指向数字 4,如下图所示。n 不等于 0,因此跳转到第 5 行,其中包含一个对 fibo() 的函数调用,这将在运行时堆栈上创建另一个活动记录。重复上述过程,直到 n=0。

需要注意的是,每个递归函数调用都有一个变量 n 的副本。活动记录保存函数范围内的所有局部变量和参数。每次调用函数时,都会创建一个新的活动记录,并将局部变量的新副本存储在活动记录中,程序运行过程的调用顺序如下图所示:

当函数执行到 n=0 时,fibo() 函数返回了它的第一个值,它将 1 返回到上一个函数调用。如下图所示,从运行时堆栈中弹出 n=0 时函数调用的活动记录(通过将图中活动记录的变为灰色来表示)。当函数返回时,活动记录的空间被回收以供以后使用。堆上的阴影对象 0 也被垃圾收集器回收,因为不再有指向它的引用。

在第一次 fibo() 函数返回之后,Python 解释器返回到前一个函数调用中的第 5 行,这个语句也包含一个 return 语句,所以函数再次返回到第 5 行,返回值为 1。同样,函数再次返回,但这次的值为 2。按照上述过程,直到 fibo() 函数返回到 main() 函数的第 8 行,整个过程如下图所示:

最后,程序打印执行结果,在第 9 行之后从 main() 函数返回,在第 11 行后从 module 返回并终止。从以上示例可以看出,对 fibo() 函数的每次递归调用都会创建自己的变量副本。每次调用该函数时,都会将局部变量和参数复制到相应的活动记录中。当函数调用返回时,相应的活动记录会从运行时堆栈中弹出。这就是递归函数的执行方式。

3.递归可视化

本节将利用 turtle 库递归的绘制图案,提高对递归过程的认识。

3.1 turtle 库简介

turtle 库属于是python的标准库,通常用于绘制图案,可以使用该库创建一只小乌龟 (turtle) 在画布上移动,当小乌龟爬行时会在画布上绘制线条,而当前尾巴抬起时,并不会进行绘制。

接下来,我们将介绍一些基本的 turtle 绘图函数:

  • turtle.penup(): turtle 抬起尾巴,之后的移动并不在图上进行绘制
  • turtle.pendown():turtle 放下尾巴,开始爬行,之后会在图上绘制其行动轨迹
  • turtle.pensize(width):用于改变画笔的宽度
  • turtle.pencolor(color):用于改变画笔颜色
  • turtle.forward(distance):向前移动 distance
  • turtle.back(distance):向后移动 distance

3.1 递归绘图

首先通过创建一个简单的递归函数 draw() 来了解 turtle 库,这个递归函数的基本情况为——要画的线长 distance 降为 0;若线长大于 0,就让小乌龟小乌龟向前绘制 distance 个单位距离,然后左转 30 度;递归情况为——缩短后的距离再次调用 draw() 函数。

# 导入 turtle 库
import turtle
# 创建小乌龟对象
my_turtle = turtle.Turtle()
# 创建用户绘制图案的窗口
window = my_turtle.getscreen()

def draw(turtle, distance):
    if distance > 0:
        # 小乌龟向前绘制 distance 个单位距离
        turtle.forward(distance)
        # 然后左转 30 度
        turtle.left(30)
        draw(turtle, distance-6)
draw(my_turtle, 200)
window.exitonclick()

接下来,我们使用 turtle 模块绘制分形树。分形树和递归有许多的共同点,是数学中的一个概念,无论放大多少倍观察分形图,总能看到相同的基本形状。

如果我们定义树为包含向左生长的子树和向右生长的子树的话,就可以根据递归的思想得到分形树:

import turtle
def tree(branch, turtle):
    if branch > 5:
        turtle.forward(branch)
        turtle.right(20)
        tree(branch-15, turtle)
        turtle.left(40)
        tree(branch-10, turtle)
        turtle.right(20)
        turtle.backward(branch)
my_turtle = turtle.Turtle()
window = my_turtle.getscreen()
my_turtle.left(90)
my_turtle.up()
my_turtle.backward(300)
my_turtle.down()
tree(110, my_turtle)
window.exitonclick()

到此这篇关于Python数据结构之递归可视化详解的文章就介绍到这了,更多相关Python递归可视化内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Python数据结构之递归可视化详解的更多相关文章

  1. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  2. ios – 嵌套递归函数

    我试图做一个嵌套递归函数,但是当我编译时,编译器崩溃.这是我的代码:编译器记录arehere解决方法有趣的…它似乎也许在尝试在定义之前捕获到内部的引用时,它是bailing?以下修复它为我们:当然没有嵌套,我们根本没有任何问题,例如以下工作完全如预期:我会说:报告!

  3. 如何在Xcode 8中启用Visual Memory Debugger?

    我将项目从以前版本的Xcode迁移到Xcode8.我想要的是使用新的可视化内存调试器.它可用于新项目,但在我导入的项目中完全缺少.为什么是这样?

  4. swift override --有一个递归问题未解决

    classca{varcount:Int{get{return1;}set{self.count=newValue;}}funcdescribe()->String{return"ca";}}classcb:ca{overridefuncdescribe()->String{return"cb";}overridevarcount:Int{get{return2;}set{//引起了递归调用,未找

  5. swift篇第一期:简单的数据结构

    首先我们可以去使用Playground来编码,并且会实时的显示对应的编码信息,这样我们就不用每次都去运行程序来显示输出的东西了哦,也方便了我们对某些语句的验证,这个是比较赞的var与let前者为可变修饰符,后者为不可变从字面意思我们就可以很好的区分了常用的类型呢,跟其他语言基本相同啦,主要有几种:1.int类型2.Float,Double类型3.String类型4.Boolean类型当我们去声明一

  6. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  7. Swift2.0语言教程之函数嵌套调用形式

    Swift2.0语言教程之函数嵌套调用形式Swift2.0语言函数嵌套调用形式在Swift中,在函数中还可以调用函数,从而形成嵌套调用。以下将对这两种调用进行详细讲解。调用方式如图7.4所示。图7.4函数嵌套的形式以下将使用函数的嵌套调用实现对s=22!这个数值,即调用f1()函数,计算22,结果为4,然后在调用f2()函数,对4的阶乘求取,计算完成22!但是在Swift语言中递归必须要有一个满足结束的条件。

  8. 【Swift】学习笔记(九)——枚举

    因为类完全可以替代枚举。不过swift中也有许多类的特性被枚举支持。这样判断必须穷举所有成员,否则就需要增加default这个选项了。使用递归枚举时,编译器会插入一个中间层。

  9. Swift实现的快速排序及sorted方法的对比

    Swift语言有着优秀的函数式编程能力,面试的时候面试官都喜欢问我们快速排序,那么用Swift如何实现一个快速排序呢?然后实现快速排序的方法:可以发现使用Swift实现快速排序的代码非常的简洁。在看完这段代码后我做了如下思考:既然是排序,那么必然可以使用系统的sorted方法,效果如何呢?对于快排最头疼的顺序性数组,sorted的重复次数只有n次!说明在面对这种类型的数组的时候sorted方法进行过判断,直接输出了。

  10. Swift 集合数据结构性能分析

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部