遞歸函數就是直接或者間接的調用自己本身的函數。 接觸遞歸的時候我們經常會看到這個程序 #include<stdio.h> #include<stdlib.h> long factorial(int n) { if (n <= 0) return 1; else return n*factorial(n - 1); } int main() { int n = 5; printf("%ld\n", factorial(n)); system("pause"); return 0; }
這就是計算階乘的一個遞歸函數!!但是它真的好嗎?答案是 no!這個程序的執行效率非常低,因爲每次調用函數時的開銷很大,不停的調用factorial()函數就要在堆棧上開闢空間(大多數編譯器都是在堆棧上完成遞歸的),這樣的函數寫出來的確是不好的!而下面這個程序也完成上面的結果:
#include<stdio.h> #include<stdlib.h> long factorial(int n) { int result = 1; while (n > 1) { result *= n; n--; } return result; } int main() { int n = 5; printf("%ld\n", factorial(n)); system("pause"); return 0; }
完成5的階乘,但是效率確高的多,這裏只用到一個循環。
提起斐波那契數列大家肯定還是想到遞歸實現:
#include<stdio.h> #include<stdlib.h> long fibonacci(int n) { if (n <= 2) return 1; return fibonacci(n - 1) + fibonacci(n - 2); } int main() { int n = 5; printf("%ld\n", fibonacci(n)); system("pause"); return 0; }
求出斐波那契數列中的第五個數,每次求值時都會使用前面的值,每一個調用都會出發兩個遞歸調用,額外的開銷非常大。但是用迭代方法實現卻是很方便:
#include<stdio.h> #include<stdlib.h> //計算Fibonacci long Fibonacci(int n) { long result = 0; long first = 0; long second = 0; result = first = 1; while (n > 2) //效率遠遠高於遞歸 { n -= 1; second = first; first = result; result = first + second; } return result; } int main() { int n = 5; printf("%ld\n",Fibonacci(n)); system("pause"); return 0; }
這個迭代的過程是這樣的:
因爲fibonacci數列的後一位是前兩位的和
second first result
1 1 2
1 2 3
2 3 5
3 5 8
......
這個效率遠高於遞歸。
看來遞歸實現一個問題並不是所有的都是好的,所以在遇到一個問題時如果你想到了遞歸,那麼你首先應該想一下這樣的遞歸的好處能否抵上完成它所付出的代價!