递归 (计算机科学)
✍ dations ◷ 2024-12-23 00:48:35 #计算机科学,控制流程,计算机编程
递归(英语:recursion)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。 递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。 绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此有很多在函数编程语言(如Scheme)中用递归来取代循环的例子。
计算机科学家尼克劳斯·维尔特如此描述递归:
递归的强大之处在于它允许用户用有限的语句描述无限的对象。因此,在计算机科学中,递归可以被用来描述无限步的运算,尽管描述运算的程序是有限的。
public void recursiveTest(){ recursiveTest(); //自己调用自己,就叫递归}
python
def RecursiveTest(): RecursiveTest() # 自己调用自己
以上两个程序是最简单的递归,但因为无限地调用自己而不会停下,就会因为栈空间溢出而导致程序产生异常而强制停止,而python会因为自身设置的保护措施(限定递归的循环次数,但该次数可更改)而不断抛出异常。
所以如果想要设计一个递归程序,就必须注意设定一个表达式判断(例如if语句)来告诉程序是否应该继续递归下去。
在支持自调用的编程语言中,递归可以通过简单的函数调用来完成,如计算阶乘的程序在数学上可以定义为:
这一程序在Scheme语言中可以写作:
(define (factorial n) (if (= n 0) 1 (* n (factorial (- n 1)))))
不动点组合子
主条目:不动点组合子
即使一个编程语言不支持自调用,如果在这语言中函数是第一类对象(即可以在运行期创建并作为变量处理),递归可以通过不动点组合子(英语:Fixed-point combinator)来产生。以下Scheme程序没有用到自调用,但是利用了一个叫做Z 算子(英语:Z combinator)的不动点组合子,因此同样能达到递归的目的。
(define Z (lambda (f) ((lambda (recur) (f (lambda arg (apply (recur recur) arg)))) (lambda (recur) (f (lambda arg (apply (recur recur) arg)))))))(define fact (Z (lambda (f) (lambda (n) (if (<= n 0) 1 (* n (f (- n 1))))))))
尾部递归是指递归函数在调用自身后直接传回其值,而不对其再加运算。尾部递归与循环是等价的,而且在一些语言(如Scheme中)可以被优化为循环指令。因此,在这些语言中尾部递归不会占用调用堆栈空间。以下Scheme程序同样计算一个数字的阶乘,但是使用尾部递归: