什么是递归
程序调用自身的编程技巧称为递归( recursion)。(既函数自己调用自己)
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的
一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小(大事化小)的问题来求解,
递归策略
只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
例子:
#include<stdio.h> int main() { printf("hehe\n"); main(); return 0; }
每一次函数调用,都要在栈区申请一块空间,main()函数内调用main()函数, 又会申请空间,会把栈区耗干,程序崩溃,栈溢出。
例题1
接受一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:1234,输出 1 2 3 4.
思路:
1234
1234%10=4
👇
1234/10=123
123%10=3
👇
123/10=12
12%10=2
👇
12/10=1
1%10=1
输入的这个数每一次%10就可以得到次数末位数字,这样就可以打印出4321,但题目要求的是正序打印即1 2 3 4
可以分析一下:
Print(1234)%10就可以得到4
Print(123) 4 -->先把123的每一位打印出来,再打印4,按照这样的思路,可以抽丝剥茧,把大的问题转化成细致的问题,一层一层往下剥,把一个大问题逐层逐层地转化成小问题
Print(12) 3 4 --> Print(1) 2 3 4
当这个函数只剩一位数时就不需要拆了,两位数以上才需要拆
void Print(unsigned int n) { if (n > 9) { Print(n / 10); } printf("%d ", n % 10); } int main() { unsigned int num = 0; scanf("%u", &num); Print(num); return 0; }
print("%d ",n%10); 也可以用%u
%u - 无符号的整数
%d - 有符号的整数
代码运行:
图解:
回到这个代码
void Print(unsigned int n)
{
if (n > 9)
{
Print(n / 10);
}
printf("%d ", n % 10);
}
如果上述代码没有/10操作,就会出现死递归,永远递归下去,所以递归要满足条件
递归的两个必要条件
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件。
例题2
2.1使用strlen函数,求字符串的长度
以下使用函数的时候必须要引用库函数#include<string.h>,strlen统计的是'\0'之前出现的字符的个数
#include<stdio.h> #include<string.h> int main() { char arr[10] = "abc"; int len1 = strlen(arr); printf("%d\n", len1); /*int len2 = my_strlen(arr); printf("%d\n", len2);*/ return 0; }
代码运行:
2.2编写函数,求字符串的长度
数组名是数组首元素的地址,当arr作为 my_strlen()的参数,传到函数内,创建指针变量char *str,代表字符串第一个字符的地址即为a的地址,创建计数器cnt,只要指针str指向的字符不是'\0',cnt++,str++.
int my_strlen(char* str) { int count = 0; while (*str != '\0') { count++; str++; } return count; } #include<stdio.h> int main() { char arr[10] = "abc"; int len = my_strlen(arr); printf("%d\n", len); return 0; }
代码运行: