在Python编程时何时不使用递归?
递归还是不递归,这是个问题。我们都知道递归函数的乐趣。但它也有自己的一系列缺点,本文将解释其中一个缺点,以帮助您明智地选择。
比如说,我们需要创建一个函数,在调用时需要打印链表中的数据。
这可以通过两种方式完成:
- 1. 使用递归
- 2. 无递归
1.递归:
```
def print_linkedlist(head):
if head is not None:
print(head.data)
print_linkedlist(head.next)
```
第一种方法也有效,但如果列表真的很长,大约有 1000 个元素,那么程序将达到递归深度和错误。不要忘记,随着列表长度的增加,堆栈大小也会线性增加。
什么是递归深度?
在我们继续之前,您应该知道这个问题是 Python 特有的。有些语言我们不会遇到这个问题,但这不会在这里讨论。我们知道递归函数调用自身。这意味着在原始函数。假设一个链表使用上面提到的递归代码从 0 到 n 按 1 计数。
第一个函数查看列表中头节点的数据,然后将其打印出来。但是第一个函数还没有结束。一个旧函数在它里面的所有函数都结束之前不能结束。如果我们观察包含当前正在运行的函数列表的调用堆栈:
# the first function waiting for
# innermost functions to end
print_linkedlist()
# the child function called
# within the first function
print_linkedlist()
调用堆栈不断增加,因为旧函数永远不会结束,因为它们正在等待内部子函数结束。最终,调用堆栈如下所示:
# original Function
print_linkedlist()
# first level function
print_linkedlist()
# second level function
print_linkedlist()
# third level function
print_linkedlist()
……
……
……
# 1000 level function – Maximum
# Recursion Depth Reached
print_linkedlist()
还有BAMMM!!!!!最大递归深度!!
递归深度计算递归函数内的活动层数。在Python中,默认的最大递归深度限制为 1000 。该限制有助于防止由无限递归引起的堆栈溢出。
因此,像下面这样的第二种方法更好,因为堆栈大小保持不变。
2. 没有递归/迭代:
```
def print_linkedlist(node):
while node:
print(node.data)
node=node.next
```
结论
递归使用起来很有趣,但您应该了解何时使用和何时不使用它。 Scala 和 Haskell 等一些语言支持一个有趣的特性,称为TAIL CALL RECURSION ,它通过在进行新调用时结束前一个函数的调用来防止递归深度问题。但是Python不支持此功能。因此,至少在Python中,如果您认为函数可能达到递归限制,则更喜欢迭代方法。