Hello everyone 我是Bladcub~
歡迎再次來到我的“一週一篇小博客“的專題欄目
-----我剛學習了函數遞歸 ,一開始也很是不懂 然後練習了很多題後 有所感悟, 在此和大家分享交流學習!!! 若有不妥的地方請大神指點一二 !!!萬分感謝!!!
劃重點:此次內容較長 !
第一步 瞭解函數遞歸
-
遞歸的定義:
一種計算過程,如果其中每一步都要用到前一步或前幾步的結果,稱爲遞歸的。用遞歸過程定義的函數,稱爲遞歸函數,例如連加、連乘及階乘等。凡是遞歸的函數,都是可計算的,即能行的 。(來自百度百科) -
遞歸是什麼?
用編程技巧通常把一個大型復 雜的問題層層轉化爲一個與原問題相似的規模較小的問題來求解,用少量的程序描述出複雜的解題過程,減少程序的代碼量。 -
遞歸的兩個必要條件
—存在限制條件,當滿足這個限制條件的時候,遞歸便不再繼續。
—每次遞歸調用之後越來越接近這個限制條件
第二步 直接上代碼感受(建議練習)
- 遞歸方式實現打印一個整數的每一位
#include<stdio.h>
void recur(int n)
{
if (n / 10 == 0)
{
printf("%d ", n);
}
else
{
recur(n / 10);
printf("%d ", n%10);
}
}
int main()
{
int n = 0;
printf("請輸入你要打印的整數:");
scanf("%d", &n);
recur(n);
return 0;
}
- 實現求n的階乘(不考慮溢出的問題)
首先是遞歸方法:
#include<stdio.h>
int fac(int n)
{
if (n < 2)
{
return 1;
}
else
{
n = n*fac(n - 1);
return n;
}
}
int main()
{
int n = 0;
printf("請輸入你的數字:\n");
scanf("%d", &n);
fac(n);
printf("他的階乘爲:%d\n", fac(n));
return 0;
}
然後放一個非遞歸方法 大家感受一下不同:
#include<stdio.h>
int fac(int N)
{
int ret = 1;
for (int i = 2; i <= N; i++)
{
ret *= i;
}
return ret;
}
int main()
{
int n = 0;
printf("請輸入你的數字:\n");
scanf("%d", &n);
fac(n);
printf("他的階乘爲:%d\n",fac(n));
return 0;
}
- 求字符串長度
遞歸:
#include<stdio.h>
int my_strlen(char *arr)
{
if (*arr != '\0')
{
return 1 + my_strlen(arr + 1);
}
else
{
return 0;
}
}
int main()
{
char arr[] = "hello world";
my_strlen(arr);
printf("字符串的長度爲:%d\n", my_strlen(arr));
}
非遞歸:
#include<stdio.h>
int my_strlen(char *arr)
{
int count = 0;
while(*arr != '\0')
{
arr++;
count++;
}
return count;
}
int main()
{
char arr[] = "hello world";
my_strlen(arr);
printf("字符串的長度爲:%d\n", my_strlen(arr));
}
- 編寫一個函數 reverse_string(char * string)(遞歸實現)
實現:將參數字符串中的字符反向排列,不是逆序打印。
要求:不能使用C函數庫中的字符串操作函數。
#include<stdio.h>
void reverse_string(char * string)
{
if (*string != '\0')
{
reverse_string(string + 1);
}
else
{
printf("%c", *string);
}
printf("%c", *string);
}
int main()
{
char *string = "abcdef";
reverse_string(string);
return 0;
}
- 寫一個遞歸函數DigitSum(n),輸入一個非負整數,返回組成它的數字之和
例如,調用DigitSum(1234),則應該返回1+2+3+4,它的和是10
輸入:1234,輸出:10
#include<stdio.h>
int DigitSum(int n)
{
if (n <10)
{
return n;
}
else
{
return n % 10 + DigitSum(n / 10);
}
}
int main()
{
int n = 0;
printf("請輸入你的數字:\n");
scanf("%d", &n);
DigitSum(n);
printf("其返回值爲:%d\n",DigitSum(n));
return 0;
}
- 編寫一個函數實現n的k次方,使用遞歸實現。
#include<stdio.h>
int biqu(int n,int k)
{
if (k <= 0)
return 1;
else
return n*biqu(n, k - 1);
}
int main()
{
int n = 0;
int k = 0;
printf("請輸入你的數字:\n");
scanf("%d", &n);
printf("次方數:\n");
scanf("%d", &k);
biqu(n,k);
printf("其k次方結果爲:%d\n", biqu(n,k));
return 0;
}
- 計算斐波那契數
遞歸:
#include<stdio.h>
int fibo(int n)
{
if (n <=2)
{
return 1;
}
else
{
return fibo(n - 1) + fibo(n - 2);
}
}
int main()
{
int n = 0;
printf("你輸入的數");
scanf("%d", &n);
fibo(n);
printf("斐波那契值爲:%d\n", fibo(n));
return 0;
}
非遞歸:
#include<stdio.h>
int fibo(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n>2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
printf("你輸入的數");
scanf("%d", &n);
fibo(n);
printf("斐波那契值爲:%d\n", fibo(n));
return 0;
}
不知道你細細的看完這些代碼,或者自己實際編寫之後有沒有感覺 遞歸就像是無限月讀 ps:哈哈哈哈資深火影迷, 如果有些代碼不是很明白可以在紙上面寫出他的過程, 慢慢計算感受。 剛開始我也是這樣子的,在這裏說一下我的感受: 一層一層的套進去,然後再一層層的反着再出來。 哈哈哈也不知道這種感受對不對
第三步 更加深入的感受
漢諾塔問題求解:
1.漢諾塔遊戲規則:每次只能移動一個盤子,並且大的盤子不能在小的盤子上面
2.解題步驟:
第一步:
把n-1個模塊 從塔1移動到塔2
把第n個模塊 從塔1移動到塔3
第二步:
把n-1個模塊 從塔2移動到塔3
3.其原理:
要解決n層的漢諾塔
就必須解決n-1層的漢諾塔
…
必須解決第1層漢諾塔
#include<stdio.h>
int i = 1;//步數
void move(int n, char a, char c)//顯示移動路徑
{
printf("第%d步 : 把第%d個盤子從%c--->移動到%c\n", i++, n, a, c);
}
void Hanoi(int n, char a, char b, char c)//遞歸算法
{
if (n == 1) move(n, a, c); //如果只有一個盤子那麼直接從A柱移到C柱
else
{
Hanoi(n - 1, a, c, b); //把A柱n-1個盤子移到B柱
move(n, a, c); //把最後一個盤子從A柱移到C柱
Hanoi(n - 1, b, a, c); //把B柱n-1個盤子移到C柱
}
}
int main()
{
int m;
scanf("%d", &m);//輸入盤子的個數
Hanoi(m, 'A', 'B', 'C');
return 0;
}
第四步 總結心得
身爲小白的我還需要多加練習!自己還有許多不懂的地方要多加深入研究,可能此次總結並不是很完美,我以後會多加學習進步的!