什么是函数递归?

程序调用自身的编程技巧称为递归(recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的 一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略:
只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
递归顾名思义也可以这样理解:递送与回归。
这里引用站上一位大佬的话:
我觉得特别贴切
“递归:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次之后,你打开面前的门后,发现只有一间屋子,没有门了。然后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这你把钥匙打开了几扇门。

   循环:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门(若前面两扇门都一样,那么这扇门和前两扇门也一样;如果第二扇门比第一扇门小,那么这扇门也比第二扇门小,你继续打开这扇门,一直这样继续下去直到打开所有的门。但是,入口处的人始终等不到你回去告诉他答案。”

再放一个通俗易懂的列子,帮助大家更好的理解递归:

我需要打开快递包装,于是买了个剪刀。但是剪刀也有包装,所以我又买了一个剪刀,这个剪刀上又有包装,所以我又买了个剪刀。。。
最后我没钱了,于是我用牙撕开了最后一个剪刀的包装,然后用这个剪刀打开了倒数第二个简单的包装,然后。。。最后用第一个剪刀打开了快递的包装,拿出了东西。
这个沙雕的过程就叫递归,递归必须要有停止条件(例子中是我把钱花完),要不然你就会拥有无数的剪刀,但又打不开快递(忘了目的系列)。

下面放几个简单的程序来进行递归的理解与使用。
1.接受一个整型值(无符号),按照顺序打印它的每一位。
void print(unsigned int n) // n=1234
{if (n > 9){print(n / 10); //123 12 1}printf("%d ", n % 10); 1 2 3 4
}int main()
{unsigned int num = 0;scanf("%u", &num);print(num);return 0;
}

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,两个指针相遇后,逆置结束

#include <stdio.h>
void reverse_string(char* arr)
{int len = strlen(arr);char tmp = *arr;*arr = *(arr + len - 1);*(arr + len - 1) = '\0';if (strlen(arr+1)>=2)reverse_string(arr + 1);*(arr + len - 1) = tmp;
}
/*或者不用指针表示:
int my_string(char* str)
{int count = 0;while (*str != '\0'){count++;str++;}return count;
}void reverse_string(char str[])
{int len = my_string(str);int tmp = str[0];str[0] = str[len - 1];str[len - 1] = '\0';if (my_string(str + 1) >= 2){reverse_string(str + 1);}str[len - 1] = tmp;
}
*/
int main()
{char arr[] = { "abc" };reverse_string(arr);printf("%s", arr);
}

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语言函数递归的简单理解(新手入门必看!!!)相关推荐

  1. C语言学习笔记知识点齐全——新手入门必看【建议收藏】

    终身受益的700个网站[史上最全]--建议收藏"卑微的小丑"总有一个可以帮助你!!! https://blog.csdn.net/liu17234050/article/detai ...

  2. c语言计算机培训,C语言计算机基础学习||新手入门必看

    本次内容笔者将完全抛弃传统教学的形式,通过自己所学所闻得出来的心得,用通俗易懂的语言结合生活,来让大家更好的认识计算机编程,更好的入门计算机基础. 笔者也想用自己的论述告诉大家,专业知识有时会比较枯燥 ...

  3. C/C++语言优秀书籍清单,新手入门必看

    大多时候,一些初学者不知道应该读什么书入门,有一定基础的开发者不知道如何进阶.本文总结了一个C++优秀书籍清单,希望能够为你带来一定的帮助.因为多读一些优秀的书籍,对于开发者稳固编程基础.提高编程技能 ...

  4. Linux新手入门必看linux的简单命令与常用快捷键

    Linux中的简单命令 一.命令的格式 常见的快捷键 二.查看命令帮助 三.date命令 2.参数说明 3.时间格式符号 4.日期格式符号 四.timedatectl命令 五. 查看目录下的文件:ls ...

  5. c语言字符串递归例子,c语言函数递归(简单的递归例子c语言)

    若在main函数中调用hanoi(3,'A','B','c')运行结果 void move(char getone,char . 分成三组: (一), 目的:将1号和2号从A移到B 调用函数:hano ...

  6. 什么叫c语言函数递归,什么是递归-C语言函数递归-嗨客网

    C语言函数递归教程 函数递归就是一个 C语言函数递归条件 执行一个函数时,就创建一个新的受保护的独立空间(新函数栈). 函数的局部 递归必须向退出递归的条件逼近,否则就是无限递归了. 当一个函数执行完 ...

  7. CAD简单圣诞树新手入门教程:

    合适CAD简单圣诞树新手入门教程: 花:1.先画花瓣 2.画两个相交的圆 3.修剪掉不用的边 4.变成花瓣 5.然后选择花瓣应用阵型工具 6.阵型数量为6个 7.这样花就画好了. 树:1.首先用圆弧命 ...

  8. C语言函数递归—经典递归问题

    目录 一.什么是递归? 二. 汉诺塔问题 2.1 认识什么是汉诺塔 2.2 汉诺塔打印步数 2.3 汉诺塔打印步骤 三.青蛙跳台阶问题 一.什么是递归? 这里我们先简单的认识一下什么是函数递归:我们可 ...

  9. C语言函数递归调用实验报告,C语言函数的递归和调用实例分析

    一.基本内容: C语言中的函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己. 要点: 1.C语言函数可以递归调用. 2.可以通过直接或间接两种方式调用.目前只讨论直接递归调用. ...

最新文章

  1. 默认参数,不固定参数 *args,**kwargs
  2. 电信 IPRAN 设备组网方案_国内首家5G核心网电信设备进网许可证;电信5G网络增强方案获认可;美国最大规模毫米波拍卖...
  3. ScriptManager.RegisterStartupScript方法和Page.ClientScript.RegisterStartupScript() 区别
  4. 摩卡业务服务管理 全面彰显强大产业推动优势——神华集团神东煤炭分公司
  5. linux centos7内核降级和升级
  6. kata_小规模流处理kata。 第1部分:线程池
  7. 内存结构 堆 栈 全局区 常量区 代码区
  8. javascript 判断string是否包含某个字符串
  9. 设计模式------简单工厂模式
  10. vue 点击div 获取位置_Vue中div contenteditable 的光标定位方法
  11. java静态代理和动态代理的区别
  12. 黑马python就业班_2017年最新黑马Python2017年就业班不加密视频教程
  13. 2022G3锅炉水处理上岗证题库及答案
  14. java可以做游戏吗_Java 能做游戏么?
  15. 处理器后面的字母含义_Intel处理器背盖上的字母含义
  16. SVPWM空间矢量脉冲宽度调制技术控制电机
  17. 剑指 Offer 14.剪绳子(动态规划、数学分析)
  18. 增加BUG的测试版本字段
  19. ubuntu从一个单纯的系统到装上自己需要的一些软件的过程
  20. 小白学习日记 eclipse的下马威

热门文章

  1. 深度学习实战之行人防碰撞预警系统
  2. 英语谚语500句(五)
  3. Android KTX
  4. 【速览】2021年中国电抗器行业市场现状分析:特高压工程建设带动高端电抗器的需求量增长[图]
  5. 在VISTA系统下使用IPX协议
  6. 再遇\xff\xfe
  7. TFT LCD 的Array制程
  8. Android开发相关配置初体验
  9. Linux常用命令——git命令
  10. unity打包的windows程序运行权限问题整理