部分函式的遞迴與迭代(非遞迴)實現
阿新 • • 發佈:2019-02-01
部分函式的遞迴和迭代(非遞迴)實現
首先,說到遞迴函式,大家一般都會想到斐波那契數列和計算階乘這兩種,書本上大多也是以這兩個為例,下面就簡單介紹一下這兩個吧。
斐波那契數列:
1 1 2 3 5 8......這樣的數列叫做斐波那契數列,規律很簡單,前兩個數字的和就是第三個數字的值。
我們可以簡單表示為:
n>2 fib(n)=fib(n-1)+fib(n-2)
fib(n)
n<=2 fib(n)=1
遞迴的實現程式碼也是比較簡單的;只需要函式不斷呼叫自身就可以了:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int fib_1(int n)//採用遞迴的方式做的 { if (n <= 2) return 1; else return fib(n - 1) + fib(n - 2); } int main() { int n = 0; scanf("%d", &n); printf("%d", fib_1(n)); system("pause"); return 0; }
當然,這看上去很容易理解,但是,這卻不是最好的方法。主要就是因為每一個遞迴呼叫都會觸發另外兩個遞迴呼叫,這樣,冗餘計算的數量增長的非常快。例如,在計算fib(10)的時候,fib(3)被呼叫了21次,而計算fib(30)的時候,fib(3)被計算了30多萬次,這很浪費,而且效率很低。
所以,我們可以用一個簡單迴圈來代替遞迴,雖然理解起來不如遞迴那麼簡單,但是效率提高了太多。
迭代的程式碼實現也是比較簡單的,只要用一個迴圈,就以a,b,c三個數字舉例吧,讓c=a+b;得到的結果給b,再把之前b的值賦給a,這樣同樣實現了斐波那契數列的規律:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int fib_2(int n)//採用函式的方式做 { int i = 0; int a = 0; int b = 1; int c = 0; if (n <= 2) return 1; else { for (i = 0; i < n - 1; i++) { c = a + b; a = b; b = c; } return c; } } int main() { int n = 0; scanf("%d", &n); printf("%d", fib_2(n)); system("pause"); return 0; }
計算階乘:
階乘大家也都知道,就是一個數不斷乘上自身的-1;也就是n*(n-1)*...*1。這可以簡單表示為:
n=0 fac(n)=1
fac(n)
n>0 fac(n)=n*fac(n-1)
遞迴的程式碼實現也是比較容易的:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int fac_1(int n) { if (n <= 0) { return 1; } else { return n*fac_1(n - 1); } } int main() { int n = 0; scanf("%d", &n); printf("%d\n", fac_1(n)); system("pause"); return 0; }
當然,這和上面的斐波那契數列一樣,效率很低,主要就是因為,在呼叫函式的時候,引數會被壓到堆疊中,為區域性變數分配記憶體空間(基本上所有的遞迴函式都是如此),每一的呼叫返回時,這些都必須還原,所以,這裡產生了很大的開銷。
同樣的,用一個簡單迴圈就可以完成相同的任務:
只要不斷乘上自身減1就可以了,知道自身不能再減為止。
程式碼實現如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int fac_2(int n)
{
int ret = 1;
while (n > 1)
{
ret *= n;
n--;
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", fac_2(n));
system("pause");
return 0;
}
這裡程式碼的簡潔性可以彌補遞迴帶來的執行時開銷,就上面所得呼叫函式時的開銷。
另外,我在這裡提一下用遞迴的方式輸出數字:
以1234這個數字為例,要求螢幕上輸出1 2 3 4;
程式碼如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
void print(int num)
{
if (num > 10)
{
print(num/10);//這裡採用遞迴的方式
}
printf("%d ", num % 10);
}
int main()
{
int num = 0;
scanf("%d", &num);
print(num);
system("pause");
return 0;
}
這裡需要對遞迴有很好的理解;還是以1234為例,第一次進入函式,1234>10,那麼會再次進入函式,不過是以123的大小進入,同樣,123還是大於10,再次以12進入,12還是大於10,那麼就再次以1進入函式,這次1<10了,那麼函式就會列印1%10的結果,就是1;
接著函式呼叫返回,列印12%10的結果,就是2;以此類推,最後輸出的結果就是4了,這樣螢幕上就會顯示出1 2 3 4 這樣的數字了;這裡就很好的演示了遞迴。
還有什麼不足敬請提出,讓我加以修改。