一、什么是遞歸
遞歸就是函數調用自己,類似於循環,使用遞歸一定要有結束遞歸的語句,這個語句一般是if條件語句。
二、遞歸與循環在一定程度上能夠等價
除了在一些算法中使用遞歸,其他的我們都用循環來解決。因為遞歸會拖累程序的速度,並且會占據很大內存。
三、尾遞歸
尾遞歸是最簡單的一種遞歸形式,函數調用自己的這一部分正好緊挨着return;
四、通過遞歸來求階乘運算
//通過遞歸來求取階乘運算
#include <stdio.h>
long rfact(int);
int main(void)
{
int num;
printf("This program calculates factorials\n");
printf("Enter a value in the range 0-12 (q to quit)\n");
while (scanf("%d",&num)==1)//1
{
if (num<0)//2
{
printf("No negative numbers,please\n");
}
else if (num>12)//3
{
printf("Keep input under 13\n");
}
else//4
{
printf("recursion %d factorials=%ld\n",num,rfact(num));
}
}
return 0;
}
//下面來定義這rfact()這個函數
long rfact(int n)//5
{
long ans;//6
if (n>1)//7
{
ans=n*rfact(n-1);//8
}
else//9
{
ans=1;
}
return ans;//10
}
下面來詳細介紹這個尾遞歸程序:
1.
輸入一個整數,如果是整數的話則進入循環,如果不是整數,則不進入循環,結束程序。
2.
循環頭判斷輸入的是不是整數,if判斷的是,輸入的是不是大於0的數,如果num<0,則在這個if else組合中,只執行if語句。
3.
else if判斷的是輸入的整數是不是大於12,如果大於12,則只執行else if這個語句。
4.
如果輸入的數據符合條件,將進入else語句,else語句將打印一句話,里面含有兩個值,一個是num的值,也就是所要求的階乘,
一個是rfact(num)的值,也就是rfact()函數的返回值,這個代表階乘大小。
5.
定義這個求階乘的函數
6.
由於需要一個long型的返回值,因此我們先定義一個long型變量
7、8、9、10
求階乘的思想:n!=n(n-1)!=n(n-1)(n-2)!......
由於我想定義的階乘函數是:rfact(),因此上面的式子又可以這樣表達:
rfact(n)=n rfact(n-1)=n (n-1) rfact(n-2)......
因此考慮到我們可以使用遞歸求取。(在每一個求階乘的式子中都可以在調用一個求階乘)
由於我們只用一重遞歸,又因為返回值就是階乘的值,因此我們可以寫出表達式:ans=n*rfact(n-1)
如何確定終止條件,對於遞歸問題,我們需要使用反向思維來確定。
階乘到最后應該是2*1,也相當於2成rfact(1),1的階乘就是1,所以我們可以讓他在這停止,也就可以把n>1當成終止條件。
假設輸入的是4,我們來分析一下這個程序到底怎么運行:
1.首先,main()函數調用這個階乘函數,4>1,因此進入if語句ans = 4 x rfact(3),同時進入第一級遞歸。
2.第一級遞歸,n=3,由於n>1,(注意,這個n相當於上一級的n-1,因此可以發現,每一級遞歸雖然變量名字一樣,但是他們所代表的是不同的變量,因為儲存的值不同),進入if語句 ans = 3 x rfact(2) ,同時進入第二級遞歸。
3.第二級遞歸,n=2,由於n>1,進入if語句 ans = 2 x rfact(1),同時進入第三級遞歸。
4.第三級遞歸,n=1,由於1=1,因此進入else語句,ans=1,接着執行下一條語句,也就是return ans;所以ans=1是rfact(1)的返回值,因此rfact(1)=1,由於不再進行遞歸,並且這一級執行完畢(return就代表結束這一級遞歸,返回到上一級遞歸處),返回上一級遞歸。
5.返回到第二級遞歸,在第二級中,程序運行到ans=2 x rfact(1),所以ans=2,接着執行下面語句,也就是return ans;所以這級遞歸執行完畢,繼續返回到上一級,並且rfact(2)=2;
6.返回到第一級遞歸,在第一級中,程序運行到ans=3 x rfact(2),所以ans=6,接着執行return ans;所以這級遞歸執行完畢,繼續返回上一級,並且rfact(3)=6;
7.返回到主函數中,在主函數中,程序運行到ans=4 x rfact(3),因此ans=24,接着執行return ans;因此rfact(4)=ans=24
*重點:
由上可知,程序是正着進入各級遞歸,倒着退出各級遞歸,並且倒出來的時候要把相應級的整個函數語句執行完畢才能往回倒。