什么是递归?
程序调用自身的编程技巧成为递归,递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转换为一个与原问题相似的规模较小的问题来求解,递归策略只需较少量的程序就可描述出结题过程所需要的多次重复计算,可以大大减少程序代码量。其主要的思考方式在于:大事化小。
递归的两个必要条件:
- 限制条件,当满足其限制条件的时候,递归便不再继续。
- 每次递归调用都是越来越接近这个限制条件。
递归经典问题:
- 汉诺塔问题
- 求n!
- 斐波那契数列求解
- ...
1.求n!(求n*n-1*n-2*....*1)
思路分析:
如果n的值为1,则可以直接求出其阶乘为1。如果n为不为1的整数,求解n的阶乘必须要有(n-1)!的值,在(n-1)!阶乘的基础上乘n即可得到n的阶乘,而求(n-1)!的值则需要求出(n-2)!的值,在此基础上乘n-1的值,所以可以得出求n!需要(n-1)!的值,求(n-1)!的值需要(n-2)!的值.......可以把这个问题拆解为多个与求解n!问题相似的规模较小的问题。
画图分析:
简单画图展示递归的过程:
向递归函数中传入n,求解n!时,我们需要知道(n-1)!的值,得到(n-1)!的值后,在此基础上乘以n即可得到n!的值,所以我们的问题现在又转为了求解(n-1)!的值,那么,求解(n-1)!的值,就是(n-1)*(n-2)!的值,即我们只需要知道(n-2)!的值,再乘上n-1就能得到(n-1)!的值了,所以现在问题又转为了求解(n-2)!的值......一直到问题解决的边缘,求解2!的值时,我们只需在1!值上再乘以2就可以了,所以问题转换为求解1!的值,直接返回1,则2!的值得到,继续返回上一级递归函数,2!的值已得到,在此基础上再乘以3得到3!,3!....层层返回,直到(n-1)!的值已得到,再向上一级返回,再乘以n即得到n!的值,至此,递归结束。
代码展示:
int factorial(int n)
{
if (n <= 1)
return 1;
return n * factorial(n - 1);
}
2.汉诺塔问题
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
思路分析:
要把所有的圆盘按照题目规定的规则从A杆移动到C杆,我们必须要借助B杆来作为中间杆,无论过程怎样移动,最大的圆盘在移动结束时一定被放在C杆的最下端,在移动的过程中要求始终保持大盘在下,小盘在上,所以移动过程中最先被放到C杆上的一定是下面最大的盘,只有最大的盘放好了,其他较小的盘才能往C杆上放,所以问题被拆解为,将最大盘放到C杆上,然后将剩余的盘放在最大盘上,但是最大盘在A杆的最下面,所以我们移动最大盘之前,要先把最大盘上面的所有盘移动到B杆上(此时C杆为中间杆),然后再把最大盘从A杆上移动到C盘上,再把剩余的盘从B杆上借助A杆移动到C杆上,然后再分析剩余的盘中的最大盘与较小盘,仍是相同的处理方法...可以看到问题被拆解为了一个个与原问题相似但规模较小的问题。
代码展示:
void hanoi(char a,char b,char c,int n)
{
if (n == 1)
printf("%c->%c\n", a, c);//边界条件:只有一个盘需要移动的时候,直接从A移动到C
else//其余情况
{
hanoi(a, c, b, n - 1);//先把n-1个盘从A借助C移动至B
printf("%c->%c\n", a, c);//把剩下的一个最大的盘从A移动到C
hanoi(b, a, c, n - 1);//把剩下的n-1个盘从B借助A移动至C
}
}
以三个盘举例(移动顺序如下):
3.斐波那契数列问题
斐波那契数列是这样一个数列:1、1、2、3、5、8、13、21、34、……,每个数都是前两个数之和,也就是说第n个数等于第n-1个数和第n-2个数的和。给定整数n,求解斐波那契数列的第n个数。
思路分析:
假设第n个斐波那契数用f(n)来表示,如果n为1,则f(n)=1,如果n为2,则f(n)=1...f(n)=f(n-1)+f(n-2)可得到递归计算式,以n==1,n==2为递归边界。
代码展示:
int fibonacci(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fibonacci(n-1) + fibonacci(n-2);
}
}
以上是递归的概念和部分经典题目分析,如有错误请指出,虚心接受意见和批评,如果觉得小Q写的还不错的话,希望给个一键三连^-^。下期见!