| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 栈模拟递归的一般性方法 二叉树非递归的后序遍历 -> 正文阅读 |
|
[数据结构与算法]栈模拟递归的一般性方法 二叉树非递归的后序遍历 |
先说结论,仅追求用栈模拟递归是有套路的(文章就是介绍我自己琢磨的一个套路),但是写出高质量的非递归代码是有难度的,还需要考虑问题本身的特征。 用栈模拟递归的可行性首先要明白函数调用的汇编层面的过程。 详情参考浅析函数的调用过程 所以一次函数调用本质上就是操作系统自动的帮我们建立、维护并回收一个内存栈,并在内存栈中保存了一些函数执行的状态信息。 递归是一种特殊的函数调用,即函数自己调用自己。函数调用是有开销的,如果递归调用的层次太深,还会有爆栈的风险。 因此,通常我们希望可以把递归程序转换为非递归程序。如前所述,用栈模拟递归是可行的。 举例说明栈模拟递归的一般套路二叉树的后序遍历是我们数据结构课都学过的例子,它的非递归写法难度是很大的。我们以此为例,供读者体会我们的套路。
用我们的套路写出来的非递归代码是这样的:
栈中存放哪些内容栈中的一个节点代表一个函数体。 栈的数据结构是我们自定义的结构体,结构体 = 递归调用函数的参数 + flag 为什么要有函数的参数很好理解,我们是模拟递归,递归有的我们一定要有。 flag就有些意思了。 先看这张图(作者是 BNUbeginner): 函数执行过程分为以下五步:
我们可以看到,递归调用类似于一个中断的过程,我们现有的函数体被中断了,转去执行新的函数体,然后从新的函数体返回,继续执行现有的函数体。 flag的作用就是标志着当前的函数体是从代码块0开始执行还是从代码块1开始执行 所有我们用flag配合switch语句(我甚至怀疑最早的switch就是针对模拟递归调用提出的,它们的功能实在是太吻合了),switch捕捉flag对应的语句块,如果执行完一个语句块要相应的增加flag序号(作者将flag的修改放在每个语句块的最前面,功能是一样的)。
因此,针对任何一个递归函数,只要我们能够将它划分成几个语句块,就可以套用模板来实现非递归方法。 效率如何我们用栈模拟递归,减少了函数调用的开销,但是我们的代码执行速度变快了吗?答案是否定的! 现代CPU都是流水线作业的,伴有大量的指令集并行。而流水线最怕的就是分支语句,分支语句往往会造成流水线的停顿或者使得一些代码的执行浪费掉了。 而对于非分支语句,无论是编译器的代码优化还是硬件的动态调度,都可以通过乱序执行很大程度上提高代码执行速度。 我们的模板伴有一个巨大的while循环,还有大量的switch-break分支跳转语句,执行速度并不比递归方式快。但是在节省内存空间方面,我们用栈模拟递归显然是十分优秀的。 回溯问题的非递归写法洛谷P1049 装箱问题,一个类似01背包的问题。可用回溯轻松完成。 对于回溯问题,我们一般不需要使用flag成员。因为回溯就是深度优先搜索,按照一颗书的形式完成搜索问题。 我们的一个函数体对应树上的一个节点。对于一个节点来说,只要它能够将它的孩子节点都扩展上,那么它的任务就完成了。 换句话说,我们不需要从子节点返回时对父节点做任何操作。 首先给出递归写法,判断边界+如果当前物品取+如果当前物品不取:
模板写法,没什么可说的,直接套用模板即可:
更优秀的非递归写法:
时间效率:
二叉树后序遍历的非递归算法
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:27:01- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |