热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分析“双重递归”详细执行顺序

很多朋友理不清“双重递归”执行顺序,下面,我以画分形树代码为例,来分析一下“双重递归”的详细执行过程和变量的变化。为了更容易理解点,画一棵小点的树。图片先定义了一个名为“tree”

很多朋友理不清“双重递归”执行顺序,下面,我以画分形树代码为例,来分析一下“双重递归”的详细执行过程和变量的变化。为了更容易理解点,画一棵小点的树。
图片分析“双重递归”详细执行顺序
分析“双重递归”详细执行顺序

先定义了一个名为“tree”的函数,并在函数内两次调用函数本身。 tree(zhichang)可以分为三分部分:“画右侧树枝”“画左侧树枝”“返回节点”。程序画树的顺序见下面步骤图:

分析“双重递归”详细执行顺序

一、下面我们先简单分析这三段代码(可跳过此段阅读):

1、画右侧树枝:先向前移动zhichang,然后向右转20度,再调用函数本身,画下一段树枝(zhichang-15),然后再右转20度,再画下一段树枝(zhichang-15),每次画树枝都比上一次短15,为了避免无休止画下去,我们加个条件zhichang>5,如果不满足这个条件,就不再向下执行。

分析“双重递归”详细执行顺序

2、画左侧树枝:
当右侧树枝不满足>5的条件时,就开始准备画左侧树枝,这时右侧树枝已经右转20度(只转了角度未开始画),所以画左侧树枝需要左转40度,再调用tree(zhichang-15)函数本身,开始画树枝。
分析“双重递归”详细执行顺序
3、当左侧树枝也不能画时,开始执行返回节点:
分析“双重递归”详细执行顺序

因为当左侧树枝不能画时,角度偏向左20度,所以返回节点时需要先右转20度,再后退zhichang的长度。
图片

上面我们先简单分析了一下代码,下面重头戏来了!

二、我们一步步地看下,双重递归如何执行的,变量又是如何变化的。

1、主函数main()先为tree()函数传进一个实参40。

2、进入tree(zhichang)函数内部,zhichang为40大于5,接着向下执行,向前画40,向右转20度。调用tree(zhichang-15)函数,本应该是顺序向下执行“左侧树枝”和“返回节点”部分,但被tree(zhichang-15)截胡了一下,所以又要从头执行完此函数后再向下执行,这里,我们记一下:第一层 zhichang=40 还欠着“左侧树枝”和“返回节点”没运行。(步骤图中的第1步)

3、调用tree(zhichang-15),zhichang-15=25,满足>5,向前画25,右转20度,再调用函数本身tree(zhichang-15),同样,再记一下,第二层:zhichang=25, 再欠一次“左侧树枝”和“返回节点”没运行。(步骤图中的第2步)

4、再调用函数本身,25-15=10,满足>5,向前画10,右转20度。第三层:zhichang=10,又欠一次“左侧树枝”和“返回节点”没运行。(步骤图中的第3步)

5、当再次调用tree(zhichang-15)时,发现zhichang-15=-5,不满足>5的条件,无法再执行tree(zhichang-5),终于该还第三层的欠帐了,向下执行 “左侧树枝”和“返回节点”部分。进入“画左侧树枝”部分,向左转40度,此时又调用了tree(zhichang-15),发现zhichang-15=-5,所以tree(zhichang-15)不能被执行,再向下执行“返回节点”部分,右转20度,回退10。(步骤图中的第4步)

6、到这里,“左侧树枝”和“返回节点”运行过了,是不是程序执行完了呢?没有!我们前面的欠帐还没有还呢?我们该还第二层的帐了!在第二层里,zhichang=25。

7、执行第二层中的“左侧树枝”和“返回节点”:

(1)先向下执行第二层中的“画左侧树枝”:
左转40度,此时又调用tree(zhichang-15),zhichang-15=10,满足>5,向下执行,向前画10,右转20度(步骤图中第5步)。再次调用tree(zhichang-15),标记一下,第二层中的第一小层:zhichang=10, 欠“画左侧节点”“返回节点”未运行。接着看,zhichang-15=-5,不满足条件,不再执行tree(zhichang-15),开始还第二层第一小层的帐,向下执行“画左侧支点”代码,发现zhichang-15=-5,不再执行tree(zhichang-15),向下执行“返回节点”代码:右转20,后退10。(步骤图第6步)第二层第一小层的欠帐还完。

(2)接着还第二层的欠帐,运行“返回节点”代码,此时zhichang=25, 右转20度,后退25。(步骤图中的第7步)。第二层的帐还完。

8、下面开始还第一层的欠帐,执行“画左侧树枝”和“返回节点”代码,在第一层中zhichang=40。

(1)执行第一层中的“画左侧树枝”

左转40度,再调用tree(zhichang-15),zhichang-15=25>5,向前画25,右转20度。(步骤图中第8步),再调用tree(zhichang-15) ……,和还第二层的账类似,不再赘叙,经过一系列函数的自我调用。实现了步骤图中的9—13步。

(2)执行第一层中的“返回节点”代码,此时zhichang=40,右转20,后退40,回到分形树的起点了。(步骤图第14步)分形树绘制完毕。

双重递归比较绕,大家得耐下心来,理清调用关系。在这段代码里,以参数变量-15进行调用,所以变量由40递减为25 、10,达到最末端后,函数再一层层返回来,所以变量又从10、25、40返回回来。


推荐阅读
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 求解连通树的最小长度及优化
    本文介绍了求解连通树的最小长度的方法,并通过四边形不等式进行了优化。具体方法为使用状态转移方程求解树的最小长度,并通过四边形不等式进行优化。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • Python如何调用类里面的方法
    本文介绍了在Python中调用同一个类中的方法需要加上self参数,并且规范写法要求每个函数的第一个参数都为self。同时还介绍了如何调用另一个类中的方法。详细内容请阅读剩余部分。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 判断编码是否可立即解码的程序及电话号码一致性判断程序
    本文介绍了两个编程题目,一个是判断编码是否可立即解码的程序,另一个是判断电话号码一致性的程序。对于第一个题目,给出一组二进制编码,判断是否存在一个编码是另一个编码的前缀,如果不存在则称为可立即解码的编码。对于第二个题目,给出一些电话号码,判断是否存在一个号码是另一个号码的前缀,如果不存在则说明这些号码是一致的。两个题目的解法类似,都使用了树的数据结构来实现。 ... [详细]
author-avatar
李劲松在科岛每晚包夜
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有