009 5道例题讲解函数递归——“C”
函数递归是什么
程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
int main()
{
printf("Fan\n");
main(); //调用自己的过程,但这个程序会出现死循环
return 0;
}
递归条件
1、存在限制条件,当满足组这个限制条件的时候,递归便不再继续
2、每次递归后越来越接近这个限制条件
递归组成部分
递推:把一个规模较大的问题分解为一个规模相对较小的相似问题
达到分解化简的目的
递归条件:函数递归不能无节制的调用下去,这样会把栈区占满,导致栈溢出
回归:将递推分解的每一步骤串起来达到最终目的
实例一
题目:接受一个整型值(无符号),按照顺序打印它的每一位。
void print(int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d", n % 10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}
思路如下:
打印1 2 3 4
转化为规模较小的相似问题
递推拆分:
先打印123 再打印4
先打印12 再打印3
先打印1 再打印2
先打印1 递推结束
递推: 打印1 2 3 4转化为打印1 2 3 转化为打印 1 2 转化为打印 1
回归:执行余下的程序 串起递推的每一个步骤
实例二
题目:不能创建临时变量的情况,求字符串的长度
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
return 1+my_strlen(str+1);
}
return 0;
}
int main()
{
char arr[10] = "abcdef";
int len = my_strlen(arr);
printf("%d", len);
}
思路如下:
求abcdef’\0’字符串的长度
转化为规模较小的相似问题
递推拆分:
先求a的长度->1再加上bcdef的长度
先求b的长度->1再加上cdef的长度
先求c的长度->1再加上def的长度
先求d的长度->1再加上ef的长度
先求e的长度->1再加上f的长度
先求f的长度->1再加上’\0’的长度
递推结束,开始回归
递推: 求abcdef的长度转化为求规模较小的bcdef长度,转化为求cdef的长度…
回归:执行余下的程序,串起递推的每一个步骤
实例三
题目:求n的阶乘
求5的阶乘54321
思路如下:
先用5 乘上fac(4) 4的阶乘
再用4 乘上fac(3) 3的阶乘
先用3 乘上fac(2) 2的阶乘
再用2 乘上fac(1) 1的阶乘
递归结束
开始回归
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", ret);
}
实例四
题目:
小乐乐走台阶
思路如下:
求走到n阶台阶一共的走法
转化为规模较小的相似问题
递推拆分:
W(n)前一步的走法有W(n-1) W(n-2)
W(n-1)前一步走法有W(n-2)与W(n-3)
W(n-2)前一步走法有W(n-3)与W(n-4)
…
W(3)前一步走法有W(2)与W(1) 递推结束,开始回归
总结
走完n阶台阶的走法=最后一步是1的走法+最后一步是2的走法
此题为斐波那契数列的经典问题:某项为前两项之和
#include <stdio.h>
int WalkWay(int n)
{
int ret;
if(n<=2) //回归条件
{
return n; //开始回归
}
else
{
return WalkWay(n-1)+WalkWay(n-2);
}
}
int main()
{
int n;
scanf("%d",&n);
int ret= WalkWay(n);
printf("%d",ret);
return 0;
}
在这里插入图片描述
实例五
题目:表示分离出 数x 的后 i 位的数字
以下提供了两种解题思路,本质上都是递归的思想,只是在回归的时候所执行余下还未执行的程序部分有所区分。
思路如下:
化为规模较小的相似问题
由于分离最后一位再简单不过
递推拆分:
先分离23908 最后一位 8
再分离2390 最后一位 0
再分离239 最后一位 9
#include <stdio.h>
// int digit(int x,int i)
// {
// if(i==1) //终止条件,开始回归
// {
// return x%10;
// }
// else //递推
// {
// return digit(x/10,--i)*10+x%10;
// }
// }
void digit(int x,int i)
{
if(i>1) //终止条件,开始回归
{
digit(x/10,i-1);
}
printf("%d",x%10);
}
int main()
{
int x,i;
scanf("%d%d",&x,&i);
digit(x,i);
return 0;
}