遞歸的原理
一個函數調用其本身,此調用過程爲遞歸(recursion)。
遞歸的使用
舉個栗子:
/*用來測試UpAndDown函數的驅動程序*/
#include <stdio.h>
void UpAndDown (int);
int main(void)
{
UpAndDown(1);
return 0;
}
void UpAndDown (int n)
{
printf("Level %d: n location %p\n" , n, &n);
if (n < 5)
UpAndDown(n+1);
printf("LEVEL %d: n location %p\n" , n, &n);
}
輸出如下:
遞歸的基本原理
每級遞歸都使用其私有變量(如例子中的n)
每次函數調用都返回前一級(調用他那級)遞歸
遞歸函數中,位於遞歸調用前的語句和各級被調函數具有相同執行順序
遞歸函數中,位於遞歸調用後的語句和各級被調函數具有相反執行順序
每級遞歸會從頭執行而不是複製其函數代碼,所以一般可代替循環語句。
遞歸函數必須包含可以終止遞歸調用的語句(如if)。
尾遞歸
最簡單的遞歸形式。
把遞歸調用語句放在函數結尾(return語句之前)。
舉個栗子:
計算n的階乘
long fact (int n) // 使用循環計算階乘,佔內存少,執行快
{
long ans;
for(ans = 1; n>1; n--)
ans *= n;
return ans;
}
long rfact (int n) // 使用遞歸計算階乘,僅作尾遞歸展示、入門
{
long ans;
if(n > 0)
ans = n * rfact(n-1);
else
ans = 1; //1.零的階乘;2.結束遞歸。
return ans;
}
遞歸和反向計算
將一個整數轉換成二進制形式。
void ToBinary (unsigned long n) // 簡單須存數組版遞歸
{
int r;
r = n % 2;
if(n >= 2)
ToBinary(n / 2);
putchar('0' + r); //or: putchar(r ? '1' : '0')
return;
}
遞歸的優缺點
- 優點
- 算法簡單
- 缺點
- 佔內存,難於閱讀和維護
舉個栗子:斐波那契數列:第一、二個數字都是1,而後續的每個數字是其前兩個數字之和。1、1、2、3、5、8、13……
long Fibonacci (int n)
{
if(n > 2)
return Fibonacci(n-1) + Fibonacci(n-2);
else
return 1;
}
雙重遞歸。
致命弱點:每級調用變量數以指數遞增!
Something interesting …
main( )也可以被自身遞歸調用或其他函數調用,儘管用得少。