递归总的来说是一种不好的编程实践吗?

19
我一直认为那些使你的代码难以跟踪且可以避免的事情被视为不良实践。递归似乎就是这些东西之一(更不用说它可能引起的问题,如堆栈溢出等),因此当我们在编程课程中必须认真学习它们时,我感到有些惊讶(因为它们通常会导致更短的代码)。而且,我发现教授们之间对此存在分歧......

人们已经针对特定语言(如Python,其中一条评论将其与goto语句进行了比较)提出了这个问题,主要是针对一个问题,但我对一般情况感兴趣:

递归在现代编程中是否被认为是一种不良实践?何时应避免使用它,并且是否有无法避免使用递归的情况?


我找到的相关问题:

递归作为一种本质上的特性吗? (未讨论递归是好还是坏)
递归是否比循环更快? (答案说明递归可能会在函数式语言中有所改善,但在其他语言中代价高昂),还有其他讨论性能的问题。


3
如果这更适合于理论计算机科学,请随意迁移。 - Neinstein
对于某些编程语言来说,这并不是基于观点的。当所选工具链或虚拟机不支持TCO时,应使用其他控制结构实现简单递归函数。对于不能处于尾部位置的调用,它们的深度应该是可预测的,例如O(log n)空间或可预测的小数据结构,以便使用简洁的递归函数,而不是使用在堆上具有实用程序堆栈的解决方案,这样可以避免增加系统堆栈的负担,使代码更易读但更加健壮。 - Sylwester
递归在需要处理大量数据(例如深度为99999999的树)时很容易出现堆栈溢出异常,因此不是一个好的选择。 - dorintufar
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
36

递归编程并不是一种不好的实践方式,它是你工具箱中的一种工具,就像任何工具一样,只有在单一使用或在不适当的上下文中使用时才会产生问题。

什么情况下应该使用递归? 当你有一个树形数据集需要执行相同逻辑时就适用。例如:您拥有一个字符串元素的树形列表,并希望计算所有字符串在一条分支线下的总长度。您可以定义一个方法来计算列表元素的长度,然后查看该元素是否有兄弟姐妹,如果有,则调用该方法并传递该兄弟姐妹 - 然后该过程重新开始。

最常见的陷阱是堆栈溢出。当列表太大无法一次性处理时,就会发生这种情况。因此,您需要实现检查以确保永远不会发生这种情况。例如将链接列表拆分成可管理的部分,在函数中利用静态变量来跟踪您遍历的级别数 - 一旦超过该数字,立即停止。

当您的数据集不是树形数据集时,请避免使用递归。我唯一能想到无法避免使用递归的情况是在不支持循环的编程语言中(如Haskell)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,