學習不易,需要堅持。
遞歸
程序調用自身的編程技巧稱爲遞歸( recursion)。遞歸做爲一種算法在程序設計語言中廣泛應用。 一個過程或函數在其定義或說明中有直接或間接調用自身的一種方法,它通常把一個大型複雜的問題層層轉化爲一個與原問題相似的規模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重複計算,大大地減少了程序的代碼量。遞歸的能力在於用有限的語句來定義對象的無限集合。一般來說,遞歸需要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。(來自百度百科)
巧用下幅圖幫助理解:
1.遞歸和非遞歸分別實現求第n個斐波那契數。
2.編寫一個函數實現n^k,使用遞歸實現
3. 寫一個遞歸函數DigitSum(n),輸入一個非負整數,返回組成它的數字之和,
例如,調用DigitSum(1729),則應該返回1+7+2+9,它的和是19
4.遞歸和非遞歸分別實現strlen
5.遞歸和非遞歸分別實現求n的階乘
6.
編寫一個函數 reverse_string(char * string)(遞歸與非遞歸實現)
實現:將參數字符串中的字符反向排列。
要求:不能使用C函數庫中的字符串操作函數。
1.
//遞歸和非遞歸分別實現求第n個斐波那契數並打印前40項
#include <stdio.h>
int fab1(int n)
{
//非遞歸
int a = 1 ;
int b = 1 ;
int c = 0 ;
if(n <= 2)
{
return 1 ;
}
else
{
int i = 1 ;
for(i = 3; i<=n; i++)
{
c = a + b ;
a = b ;
b = c ;
}
}
return c ;
}
int fab2( int n)
{
//遞歸
if(n <= 2)
{
return 1 ;
}
else
{
return fab2(n - 1) + fab2(n - 2) ;
}
}
void Fab()
{
int i = 0 ;
int arr[40] = { 1, 1, 0 } ;
for(i=2; i<40; i++)
{
arr[i] = arr[i-1] + arr[i-2] ;
}
for(i=0; i<40; i++)
{
printf("%10d ", arr[i]) ;
if(0 == (i + 1) % 5)
printf("\n") ;
}
printf("\n") ;
}
int main()
{
int m = 0 ;
int order = 0 ;
int ret1 = 0 ; //用來接收非遞歸求得的值
int ret2 = 0 ;// 用來接收遞歸求得的值
printf("----------此程序用來計算斐波那契數列----------\n") ;
printf("\n請輸入你想要計算第幾個數列的值: ") ;
scanf("%d", &order) ;
ret1 = fab1(order) ;
ret2 = fab2(order) ;
printf("非遞歸求得第%d個斐波那契數列值爲: %d\n", order, ret1) ;
printf("遞歸求得第%d個斐波那契數列值爲: %d\n", order, ret2) ;
printf("\n----------將打印出前項斐波那契數列值----------\n") ;
Fab() ;
return 0 ;
}
運行結果:
//編寫一個函數實現n^k,使用遞歸和非遞歸實現
#include <stdio.h>
int func1(int n, int k)
{
//非遞歸
int i = 1 ;
int ret = 1 ;
while(i <= k)
{
ret = ret * n ;
i++ ;
}
return ret ;
}
int func2(int n, int k)
{
//遞歸
if(0 == k)
{
return 1 ;
}
else if(1 == k)
{
return n ;
}
else
{
return n * func2(n, k-1) ;
}
}
int main()
{
int n = 0 ;
int k = 0 ;
int ret1 = 0 ;
int ret2 = 0 ;
printf("----------此程序用來計算n的k次冪----------\n") ;
printf("\n請給n和k賦值: ") ;
scanf("%d%d", &n, &k) ;
ret1 = func1(n, k) ;
ret2 = func2(n, k) ;
printf("\n非遞歸求得%d^%d = %d\n", n, k, ret1) ;
printf("遞歸求得%d^%d = %d\n", n, k, ret2) ;
printf("\n") ;
return 0 ;
}
運行結果:
// 寫一個遞歸函數DigitSum(n),輸入一個非負整數,返回組成它的數字之和,
//例如,調用DigitSum(1729),則應該返回+7+2+9,它的和是
#include <stdio.h>
int DigitSum(int n)
{
int m = 0 ;
int sum = 0 ;
if(n != 0)
{
m = n % 10 ;
n = n / 10 ;
sum= m + DigitSum(n) ;
}
return sum ;
}
int main()
{
int n = 0 ;
int ret = 0 ;
printf("請輸入一個非負整數: ") ;
scanf("%d", &n) ;
ret = DigitSum(n) ;
printf("各位和爲%d\n", ret) ;
return 0 ;
}
//用遞歸和非遞歸模擬實現strlen()函數
#include <stdio.h>
int My_strlen1(char* p)
{
//非遞歸
int count = 0 ;
while(*p != '\0')
{
p++ ;
count++ ;
}
return count ;
}
int My_strlen2(char* str)
{
//遞歸
if(*str != '\0')
return 1+My_strlen2(str + 1) ;
else
return 0 ;
}
int main()
{
int lenth1 = 0 ;
int lenth2 = 0 ;
char str[] = "Happy" ;
lenth1 = My_strlen1(str) ;
lenth2 = My_strlen2(str) ;
printf("----------此程序用來模擬實現strlen()函數----------\n") ;
printf(" 非遞歸求得\"Happy\" 長度爲: %d\n", lenth1) ;
printf(" 遞歸求得\"Happy\" 長度爲: %d\n", lenth2) ;
return 0 ;
}
運行結果:
//遞歸和非遞歸分別實現求n的階乘
#include <stdio.h>
int fun1(int n)
{
//非遞歸
int mul = 1 ; //保存乘積
while(n > 0)
{
mul = mul * n ;
n-- ;
}
return mul ;
}
int fun2(int n)
{
//遞歸
if(n <= 1)
{
return 1 ;
}
else
{
return n * fun2(n - 1) ;
}
}
int main()
{
int n = 0 ;
int ret1 = 0 ;
int ret2 = 0 ;
printf("----------此程序來計算n的階乘----------\n") ;
printf("請輸入n的值: ") ;
scanf("%d", &n) ;
ret1 = fun1(n) ;
ret2 = fun2(n) ;
printf("非遞歸求得%d! = %d\n",n, ret1) ;
printf("遞歸求得%d! = %d\n",n, ret2) ;
return 0 ;
}
運行結果:
6.
//編寫一個函數 reverse_string(char * string)(遞歸與非遞歸實現)
//實現:將參數字符串中的字符反向排列。
//要求:不能使用C函數庫中的字符串操作函數。
#include <stdio.h>
#include <string.h>
int My_strlen(char* str)
{
int lenth = 0 ;
if(*str == '\0')
{
return 0 ;
}
while(*str != '\0')
{
str++ ;
lenth++ ;
}
return lenth ;
}
void Reverse_string1(char* str)
{
//非遞歸
int left = 0 ;
int right = My_strlen(str) - 1 ;
while(left <= right)
{
char temp = str[left] ;
str[left] = str[right] ;
str[right] = temp ;
left++ ;
right-- ;
}
}
void Reverse_string2(char* str)
{
//遞歸
char* p = str ;
if(*p == '\0')
{
return ;
}
else
{
Reverse_string2(p+1) ;
printf("%c", *p) ;
}
}
int main()
{
char str[] = "gfedcba" ;
printf("----------此程序將字符串逆轉----------\n") ;
printf("逆轉前字符串爲: %s\n", str) ;
printf("遞歸逆轉後字符串爲: ") ;
Reverse_string2(str) ;
printf("\n") ;
Reverse_string1(str) ;
printf("非遞歸逆轉後字符串爲: %s\n", str) ;
printf("\n") ;
return 0 ;
}