对于C语言函数递归的简单理解(新手入门必看!!!)
什么是函數遞歸?
程序調用自身的編程技巧稱為遞歸(recursion)。 遞歸做為一種算法在程序設計語言中廣泛應用。 一個過程或函數在其定義或說明中有直接或間接 調用自身的 一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞歸策略: 只需少量的程序就可描述出解題過程所需要的多次重復計算,大大地減少了程序的代碼量。 遞歸的主要思考方式在于:把大事化小 遞歸顧名思義也可以這樣理解:遞送與回歸。 這里引用站上一位大佬的話: 我覺得特別貼切 “遞歸:你打開面前這扇門,看到屋里面還有一扇門。你走過去,發現手中的鑰匙還可以打開它,你推開門,發現里面還有一扇門,你繼續打開它。若干次之后,你打開面前的門后,發現只有一間屋子,沒有門了。然后,你開始原路返回,每走回一間屋子,你數一次,走到入口的時候,你可以回答出你到底用這你把鑰匙打開了幾扇門。循環:你打開面前這扇門,看到屋里面還有一扇門。你走過去,發現手中的鑰匙還可以打開它,你推開門,發現里面還有一扇門(若前面兩扇門都一樣,那么這扇門和前兩扇門也一樣;如果第二扇門比第一扇門小,那么這扇門也比第二扇門小,你繼續打開這扇門,一直這樣繼續下去直到打開所有的門。但是,入口處的人始終等不到你回去告訴他答案。”
再放一個通俗易懂的列子,幫助大家更好的理解遞歸:
我需要打開快遞包裝,于是買了個剪刀。但是剪刀也有包裝,所以我又買了一個剪刀,這個剪刀上又有包裝,所以我又買了個剪刀。。。
最后我沒錢了,于是我用牙撕開了最后一個剪刀的包裝,然后用這個剪刀打開了倒數第二個簡單的包裝,然后。。。最后用第一個剪刀打開了快遞的包裝,拿出了東西。
這個沙雕的過程就叫遞歸,遞歸必須要有停止條件(例子中是我把錢花完),要不然你就會擁有無數的剪刀,但又打不開快遞(忘了目的系列)。?
2.編寫函數不允許創建臨時變量,求字符串的長度。
int my_strlen(char* s) {if (*s != '\0'){return 1 + my_strlen(s + 1);}else{return 0;} }int main() {char arr[10] = { "abcdaaaa" };int len = my_strlen(arr);printf("%d\n", len);return 0; }3.求n的階乘。
int Fac(int n) {if (n <= 1){return 1;}else{return n*Fac(n - 1);} } int main() {int n = 0;scanf("%d", &n);int ret = Fac(n);printf("%d\n", ret);return 0; }4.求斐波那契數列底n個數的值。
int Fib(int n) {if (n <= 2)return 1;elsereturn Fib(n - 1) + Fib(n - 2); }int main() {int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d\n", ret);return 0; }?5.字符串逆序(遞歸實現)【將參數字符串中的字符反向排列,不是逆序打印。】
| 思路: | |
| 逆置字符串,循環的方式實現非常簡單 | |
| ? 1. 給兩個指針,left放在字符串左側,right放在最后一個有效字符位置 | |
| ? 2. 交換兩個指針位置上的字符 | |
| ? 3. left指針往后走,right指針往前走,只要兩個指針沒有相遇,繼續2,兩個指針相遇后,逆置結束 |
6.計算一個數的每位之和(遞歸實現)
#include <stdio.h> int DigitSum(int n) {if (n > 9){return DigitSum(n / 10) + n % 10;}elsereturn n; }int main() {int n = 0;scanf("%d", &n);int ret = DigitSum(n);printf("%d\n", ret); }7.遞歸實現n的k次方?
#include <stdio.h> int pow(int n, int k) {if (k == 0)return 1;else if (k >= 1)return n*pow(n, k - 1); } int main() {int n = 0;int k = 0;scanf("%d %d", &n, &k);int ret = pow(n, k);printf("%d\n", ret);return 0; }8.? 求 1+2+3....+n 的值 。
#include <stdio.h> int sum(int n) {if (n == 1)return 1; // 出口 (必要的)elsereturn (sum(n - 1) + n); //根據表達式 F(n)=f(n-1)+n 取等號后邊式子 稱為 遞推關系式 } int main() {int n = 0;scanf("%d", &n);int ret = sum(n);printf("%d\n", ret);/*int num = sum(100);printf("%d\n", num);*/return 0; }9. 已知一個整形數組,求出前n項數字之和。
#include <stdio.h> int sum(int arr[], int n) {if (n == 0)return arr[0];elsereturn sum(arr, n - 1) + arr[n]; } int main() {int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int ret = sum(arr, 4);printf("%d\n", ret);return 0; }10.??求一個已知數組里面前n個數字里面的最大值 (下標為n計算)
#include <stdio.h> int max(int arr[], int n) {if (n == 0)return arr[0];else if (max(arr, n - 1) > arr[n])return max(arr, n - 1);elsereturn arr[n]; } int main() {int arr[] = { 7, 4, 8, 6, 3, 2, 9, 11, 5 };int n = 0;scanf("%d", &n);int ret = max(arr, n);printf("%d\n", ret);return 0; }11.??遞歸中的冒泡排序
void bubble(int arr[], int L, int R) {if (L < R){int i = 0;for (i = L; i <= R - 1; i++){if (arr[i] > arr[i + 1]){int tmp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = tmp;}}bubble(arr, L, R - 1);} } int main() {int i = 0;int arr[7] = { 7, 6, 5, 4, 3, 2, 1 };bubble(arr, 0, 6);for (i = 0; i < 7; i++){printf("%d ", arr[i]);}return 0; }12.求兩數最大公約數?
int gcd(int a, int b) {if (a%b == 0)return b;else{int r = 0;r = a%b;return gcd(b, r);} } int main() {int a = 0;int b = 0;scanf("%d %d", &a, &b);int ret = gcd(a, b);printf("%d\n", ret); }總結:
什么時候用遞歸:
1.當解決一個問題遞歸和非遞歸都可以使用,且沒有明顯問題。那就可以使用遞歸。
2.當解決一個問題遞歸寫起來很簡單,非遞歸比較復雜,且遞歸沒有明顯問題,那就用遞歸。
3.如果說用遞歸解決問題,寫起來簡單,但是有明顯問題,那就不能使用遞歸。得寫出非遞歸的方式來解決。
小tips :
?遞歸想的深入了,很容易被繞進去,這時我們就要記住“ 我們是懶懶的老和尚,計算機就是忙碌的小和尚,我們不要管他們。”? 把它想成,在還沒有到達遞歸函數出口位置時,在做重復的事情就可以了。既然是重復的事情就沒有必要每一樣都去驗證了 。
總結
以上是生活随笔為你收集整理的对于C语言函数递归的简单理解(新手入门必看!!!)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2017年我国电力供需形势预测分析 清洁
- 下一篇: OOP版电子词典