先说答案,是的,所有的递归代码都可以转化为非递归代码。之所以所有的递归都可以转化为迭代算法,是因为递归使用了函数调用,而函数调用本身是根据调用栈的结构来实现的,但是这一切都是自动完成的。当然我们也可以用代码手动模拟一下。我们知道,所有的递归调用展开后,实际上会形成一棵树。递归转非递归无非就是遍历这棵树。然后还有很多遍历树的技巧。Depth-firsttraversalbasedonstackdepth-firsttraversal,orQueue-basedbreadth-firsttraversalismobile:据说递归转换为非递归的题目,更理论化的解释是这个,不管是递归还是非递归-recursive,两者都是Turingcomplete,既然是Turing-complete,那么在表达能力上是等价的,不存在谁不能转化为谁的问题。图灵完备性参考这篇文章《计算机科学中那些有趣的事实》。但是有一个难度问题。我们都知道尾递归是最容易转化为非递归迭代形式的。本质上,这棵树不是多叉的而是单叉的。单叉树不会退化成链表吗?遍历链表当然简单,但是如果是多叉,问题就不那么简单了。这里最有意思的是没有模板可以让我们以例程的形式直接将递归转为非递归,所以这里就有一个问题:为什么要将递归转为非递归?非递归呢?因为最终你会发现,将递归转为非递归,无非是你接手了编译器已经为你完成的工作,你会发现自己手动mocking了函数调用。递归的优点很明显:代码简洁,易于理解和维护,它的缺点是执行效率“可能”不如非递归版本高,但你最好明白这句话是什么意思说来说去,哪里效率不高?我们知道函数调用本身并不是免费的,函数调用也是有成本的。这里的代价是需要执行一些额外的指令来维持函数调用和函数返回。这部分请参考《??函数调用时底层发生了什么???》。同时,栈区空间是有限的,所以如果你的递归调用层数太多,可能会导致栈溢出,炸毁你的运行环境,可能会出现双重计算问题(可以使用内存表解决),除非你有绝对命令有令人信服的理由,否则你不应该尝试将递归转换为非递归。
