文 | 太阳雪html
来源:Python 技术「ID: pythonall」python
编程之因此魅力无比,其中一个重要的缘由是,一次写入,屡次运行,你可能和我同样想象过这样的场景:半躺在椅子上,优雅的点击一个按钮,新的宇宙启动了……程序员
不要以为这是个幻想,也别只将其停留在幻想之中,这个幻想说明了一个问题,程序能够帮助咱们完成更多的事情,而起始点无比的简单,今天咱们一块儿聊聊递归的事情,也许它就是启动宇宙的那个小小按钮算法
一种计算过程,若是其中每一步都要用到前一步或前几步的结果,称为递归的。用递归过程定义的函数,称为递归函数,例如连加、连乘及阶乘等。凡是递归的函数,都是可计算的,便可行的。编程
古典递归函数,是一种定义在天然数集合上的函数,它的未知值每每要经过有限次运算回归到已知值来求出,故称为“递归”。它是古典递归函数论的研究对象编程语言
递归做为一种算法思想,应用的场景不少,例如著名的汉诺塔问题,即有三个柱子,最左边的上面从小到大串着必定数量的盘子,如今须要将它们移动到最右边的柱子上,原则是移动过程当中,以及最终的结果,必须保存小盘子在大盘子上面ide
汉诺塔函数
还有斐波那契数列,即除了第一个和第二个数为1,其他的数都是前两个数之和,例如 1,1,2,3,5,8……,还有阶乘算法,即,正整数列中,个数为 n 的数相乘,等等举不胜举工具
在计算机算法中递归更经常使用,例如二分法查找,快速排序,树的遍历,即对于执行规模不肯定,但能拆解为简单步骤的算法,递归几乎都有用武之地,不但能够解决问题,并且语义也更清晰优化
平常应用中,递归也很广泛,例如遍历文件夹查找文件,处理 XML 文件,再例如 应收帐款和收款的匹配,还有最近我 在 TMS 项目遇到的处理箱单层层包裹的关系问题,等等举不胜举
递归与其说是一种编程语言的能力,不如说是一种分析和思考问题的能力,从问题中发现规律,将大问题转换为小问题,知道能够简单计算为止,或者正向思考,前面步骤是后面步骤的计算条件,不断的计算前面的结果,最终获得预订步骤的结果。
既然递归如此好,有没有限制呢?固然有,任何事物都具备两面性,解决问题时要扬长避短
终于到了实践部分了,为您的耐心点赞,咱们用递归算法画一棵分形树
分形树就是一棵树的局部形状和总体形状类似,天然界中很常见,例如一片叶子上的形状,和整棵树的形状类似,即整棵树由样式相同的无数个从小到大的形状构成
天然分形树
那么如何用程序画出一个分形树呢?能够先画最小的,而后画次大的,最后组成整个形状,就是今天聊的 递归算法
既然要画,就须要安装一个画库工具,Python 中有各式各样的绘图包,咱们选用 Turtle 库,库如其名,能够将 Turtle 想象成一个小乌龟,逐渐在海滩上移动,画出一个图形来,经过将简单图形组合起来,能够轻松地绘制出精美的形状和图案
安装
> pip install turtle
有了这些概念,就能够经过代码来设置画布,控制画笔绘制图形了,代码很简单:
from turtle import Turtle myTurtle = Turtle() myTurtle.forward(100)
有了绘制工具,就解决了技术问题,如今能够专心思考算法了
为了简便,选择最简单的二叉分形树来画,最基本形状是一个二叉树,由树干和左右两个枝叉组成,左右树杈于树干的夹角设置为 20 度,像一个 Y 字
常规思惟:先画根树干,而后分别画两个树杈,每一个树杈又是一棵树,接着在各自的树干上再画出两个树杈,如此循环往复,直到画出最小树的两个树杈为止
是否是有点绕?下面的图片展现了部分绘制过程,可能更直观:
直接上代码:
from turtle import Turtle # 分形树递归方法 def fractalTree(branchLen, t): if branchLen > 0: t.forward(branchLen) t.right(20) fractalTree(branchLen - 15, t) t.left(40) fractalTree(branchLen - 15, t) t.right(20) t.backward(branchLen) # 初始化画布和画笔 t = Turtle() # 建立画布实例 t.screen.delay(3) # 设置绘制显示延迟,以便观察过程 t.pensize(2) # 设置画笔粗细为 2 个像素 t.color('green') # 设置画笔颜色为 绿色 t.left(90) # 向左旋转 90 度,即让画笔朝上 t.up() # 抬起画笔,即在移动时不会绘制 t.backward(300) # 相对画笔朝向,向后退 300 个像素 t.down() # 落下画笔,准备绘制 # 绘制分形树,根树干长度为 105 像素 fractalTree(105, t) # 获取画布窗口,并设置关闭条件为点击窗口,以便在执行完成后保留绘图窗口 t.getscreen().exitonclick()
上面代码分为三部分,Turtle 引入、分形树方法定义,以及分形树绘制
Turtle 引入没必要解释,分形树绘制部分有详细注释,也没必要多说,主要分析下分形树方法 fractalTree:
总体上看,过程就是,画树干,而后画右侧分枝,再画左侧分枝,最后回到起点,不过在画两侧分枝时,咱们用了递归,让画树的过程获得重复利用,若是顺利,就会看到上面展现的绘制过程,赶忙试试吧
看似上面过程很顺利,其实否则,我在编写代码时,不断的陷入思惟的漏洞,要么是设置错了画笔方向,要么是画笔没有回退到位,等等,乌龙无数(汗!),看下翻车记录:
失败案例1
再来一个
失败案例2
不过也挺好看的,不是吗
今天经过画一颗分形树,了解了一下递归的概念和应用,总体感受递归代码短小,但思考过程比正常编程过程要复杂的多,不过这就是编程的魅力,更确切的说是数学的魅力,用简单的符号语言,描绘纷繁复杂的世界…… 最重要的是,Python 支持递归 示例代码中,不只有分形树方法及翻车代码,还有个彩蛋,欢迎把玩