递归(Recursion)是指在函数的定义中使用函数自身的方法。实际上,递归,顾名思义,其包含了两个意思:递 和 归,这正是递归思想的精华所在。以下是用递归方法进行最大公约数的求法:
#include <stdio.h>
int hcf(int n1, int n2);
int main()
{
int n1, n2;
printf("输入两个正整数: ");
scanf("%d %d", &n1, &n2);
printf("%d 和 %d 的最大公约数为 %d", n1, n2, hcf(n1,n2));
return 0;
}
int hcf(int n1, int n2)
{
if (n2 != 0)
return hcf(n2, n1%n2);
else
return n1;
}
这个程序的思想来源于辗转相除法,采用递归的思想,将两数的取余作为一个新数,与上一次的一个数求最大公约数,由于这两组数的最大公约数一样,所以,可以再次返回调用这个函数,直到不能再取余数,最后得到的就是最大公约数。
此外,九章算数中记载了另一种方法,但总体思路一样,叫做更相减损术。
#include <stdio.h>
int main()
{
int n1, n2;
printf("输入两个数,以空格分隔: ");
scanf("%d %d",&n1,&n2);
// 如果输入的是负数,将其转换为正数
n1 = ( n1 > 0) ? n1 : -n1;
n2 = ( n2 > 0) ? n2 : -n2;
while(n1!=n2)
{
if(n1 > n2)
n1 -= n2;
else
n2 -= n1;
}
printf("GCD = %d",n1);
return 0;
}
在最初,这种方法是用来约分分数的,所以此处有正负数之分,他是将每次的差值与减数作为新的环节。为了理解这种方法,我们可以设出一个n1与n2的最大公约数x。那么n1=N1x,n2=N2x。N代表对应的系数,且N1与N2是互质的,因为如果不是互质的,那么x就不是最大公约数。N1与N2可以是负数。(N1-N2)x与N2x的最大公约数肯定是x,那么我们就将N1与N2的最大公约数这个问题,转化成了(N1-N2)x与N2 x的最大公约数这个问题。进行循环的转化,最终会得到一个系数为一的x,这个x就是它的最大公约数。相应的,n1与n2的最大公倍数,一定是x的倍数,又因为N1与N2是互质的,所以最大公倍数等于N1*N2*x。
与之相似的问题还有很多,但方法都是一样的,将一个问题转化为一个或者n个相似的问题,循环递归,就可以得到解决这个问题的答案,譬如小青蛙跳台阶的问题,斐波纳契数列的第n项求解,甚至是阶乘以及汉诺塔游戏,都可以通过这种思路进行解决。人理解迭代,神体会递归,这种算法巧妙至极,学无止境。