C语言通过运行时堆栈支持递归函数的实现,递归函数时直接或者间接调用自身的函数,经常有人拿斐波那契实现当做递归的实现,然后这样做效率并不高。
n < 1; Fib(1) =1
n = 2; Fib(2) = 1
n > 2; Fib(n) = Fib(n - 1) + Fib(n - 2);
由于每个递归调用都会触发另外两个递归调用,而这两个调用还将继续触发下去,这样会有大量的冗余计算。例如:计算Fib(10)过程,Fib(3)被计算了21次;
#include <stdio.h> int fib(n) { static count = 0; if (n <= 2) return 1; if (n == 3) { count++; printf("调用fib(3) %d 次 ", count); } return fib(n - 1) + fib(n - 2); } int main() { printf("%d", fib(10)); while (1) ; return 0; }
调用21次:
除了一次调用之外其他的全部是多余的计算,由于函数是尾递归,所以可以方便的转换为迭代循环来实现
下面通过迭代的方法来实现
long fib(int n) { long result; long previous_result; long previous_older_result; result = previous_result = 1; while (n > 2) { n -= 1; previous_result = result; previous_older_result = previous_result; result = previous_result + previous_older_result; } return result; }
递归带来的好处是可读性,但不正确的使用也会使开销也会增大。
下面是一个利用递归把整数转换成字符形式,如4321转换成'4','3', '2', '1'。
void num_to_char(int num) { int quotient; quotient = num / 10; if (quotient != 0) { num_to_char(quotient); } printf("%c", num % 10 + '0'); }
递归函数每次执行时必须越来越接近出口,这里的出口就是 quotient 为 0时。