zoukankan      html  css  js  c++  java
  • python递归可视化

    4.4 递归可视化

      前文探讨了一些能用递归轻松解决的问题。但是,要想象递归的样子或者将递归过程可视化仍然十分困难。

    这使得递归难以掌握。本节将探讨一系列使用递归来绘制有趣图案的例子。看着这些图案一点一点地形成,

    你会对递归过程有新的认识,从而深刻地理解递归的概念。

      我们将使用Python的turtle模块来绘制图案。Python的各个版本都提供turtle模块,它用起来非常简便。

    顾名思义,可以用turtle模块创建一只小乌龟(turtle)并让它向前或向后移动,或者左转、右转。小乌龟的

    尾巴可以抬起或放下。当尾巴放下时,移动的小乌龟会在其身后画出一条线。若要增加美观度,可以改变小乌

    龟尾巴的宽度以及尾尖所蘸墨水的颜色。

      让我们通过一个简单的例子来展示小乌龟绘图的过程。使用turtle模块递归地绘制螺旋线,如代码清单4-5

    所示。先导入turtle模块,然后创建一个小乌龟对象,同时也会创建用于绘制图案的窗口。接下来定义

    drawSpiral函数。这个简单函数的基本情况是,要画的线的长度(参数len)降为0。如果线的长度大于0,

    就让小乌龟向前移动len个单位距离,然后向右转90度。递归发生在用缩短后的距离再一次调用drawSpiral

    函数时。代码清单4-5在结尾处调用了myWin.exitonclick()函数,这使小乌龟进入等待模式,直到用户在

    窗口内再次点击之后,程序清理并退出。

    代码清单4-5 用turtle模块递归地绘制螺旋线

    from turtle import *
    
    myTurtle = Turtle()
    mywin = myTurtle.getscreen()
    def drawSpiral(myTurtle, lineLen):
        if len > 0:
            myTurtle.forward(lineLen)
            myTurtle.right(90)
            drawSpiral(myTurtle, lineLen-5)
    
    drawSpiral(myTurtle, 100)
    mywin.exitonclick()
    


      理解了这个例子的原理,便能用turtle模块绘制漂亮的图案。接下来绘制一棵分形树。分形是数学的一

    个分支,它与递归有很多共同点。分形的定义是,不论放大多少倍来观察分形图,它总是有相同的基本形

    状。自然界中的分形例子包括海岸线、雪花、山岭,甚至树木和灌木丛。众多自然现象中的分形本质使得

    程序员能够用计算机生成看似非常真实的电影画面。下面来生成一棵分形树。

      思考如何用分形来描绘一棵树。如前所述,不论放大多少倍,分形图看起来都一样。对于树木来说,

    这意味着即使是一根小嫩枝也有和一整棵树一样的形状和特征。借助这一思想,可以把树定义为树干,

    其上长着一棵向左生长的子树和一棵向右生长的子树。因此,可以将树的递归定义运用到它的左右子树上。

      让我们将上述想法转换成Python代码。代码清单4-6展示了如何用turtle模块绘制分形树。仔细研究

    这段代码,会发现第5行和第7行进行了递归调用。第5行在小乌龟向右转了20度之后立刻进行递归调用,

    这就是之前提到的右子树。然后,第7行再一次进行递归调用,但这次是在向左转了40度以后。之所以

    需要让小乌龟左转40度,是因为它首先需要抵消之前右转的20度,然后再继续左转20度来绘制左子树。同

    时注意,每一次进行递归调用时,都从参数branchLen中减去一些,这是为了让递归树越来越小。

    第2行的if语句会检查branchLen是否满足基本情况。

      代码清单4-6 绘制分形树

    def tree(branchLen,t):
        if branchLen > 5:
            t.forward(branchLen)
            t.right(20)
            tree(branchLen-10,t)
            t.left(40)
            tree(branchLen-10,t)
            t.right(20)
            t.backward(branchLen)
    

     
      请执行分形树的代码,但在此之前,先想象一下绘制出来的树会是什么样。这棵树是如何开枝散叶的呢?

    程序是会同时对称地绘制左右子树,还是会先绘制右子树再绘制左子树?在输入tree函数的代码之后,可以用

    下面的代码来绘制一棵树。

    drawSpiral(myTurtle, 100)
    mywin.exitonclick()
    myTurtle.left(90)
    myTurtle.up()
    myTurtle.backward(350)
    myTurtle.down()
    myTurtle.color("green")
    tree(110,myTurtle)
    mywin.exitonclick()
    


      注意,树上的每一个分支点都对应一次递归调用,而且程序先绘制右子树,并一路到其最短的嫩枝,如图

    4-7所示。接着,程序一路反向回到树干,以此绘制完右子树,如图4-8所示。然后,开始绘制左子树,但并不

    是一直往左延伸到最左端的嫩枝。相反,左子树自己的右子树被完全画好后才会绘制最左端的嫩枝。

                      

                          图4-7 先绘制右子树

                          


                                                                       图4-8 分形树的右半部分

      这个简单的分形树程序仅仅是一个开始。你会注意到,绘制出来的树看上去并不真实,这是由于自然界并不

    如计算机程序一样对称。在本章最后的练习中,你将探索如何绘制出看起来更真实的树。


  • 相关阅读:
    优先队列用法详解
    chenzl
    2020面向对象程序设计寒假作业1
    1.自我介绍

    洛谷U32670 小凯的数字(比赛)
    洛谷1417 烹调方案
    高等软工课程总结
    西电B楼导航
    毕业前夕随想
  • 原文地址:https://www.cnblogs.com/mtfan01/p/14822317.html
Copyright © 2011-2022 走看看