一、概念
直接或间接调用自身的算法称为递归
二、条件
(1)给递归定义的初始值
(2)用较小的自变量的函数值来表示较大自变量的函数值
三、思想
问题规模较大,解决该问题时较困难。因此考虑将问题规模较大的问题分割成一些规模较小的相同的子问题,反复使用这种方式,直至使子问题缩小到极易求解。得出答案的过程为逆过程,先解决规模较小的极易求解的子问题,然后依次扩大问题规模,直至得出问题答案。
四、例子
(1)阶乘函数
实现代码
1. int factorial(int n)
2. {
3. if(n == 0) return 1;
4. return n * factorial(n - 1);
5. }
定义域n为非负值,递归的第一式给出了函数初始值,是非递归定义的,第二式给出了用较小自变量函数值来表示较大自变量函数值的方式来定义n的阶乘。
(2)Fibonacci数列
实现代码
1. int fibonacci(int n)
2. {
3. if(n <= 1) return 1;
4. return fibonacci(n - 1) + fibonacco(n - 2);
5. }
递归的实现从第三项开始,后一个数是前两个数的和。
(3)排列问题
设
Ri={r1,r2,…rn}
是要进行排列的n个元素,
Ri=R−{ri}
。集合X中元素的全排列记为
Perm(X)
。
(ri)Perm(X)
表示在全排列
Perm(X)
的每一个排列前加上前缀
ri
得到的排列。
R
的全排列可归纳定义为:
当
当
n>1
时,
Perm(R)
由
Perm(R1)
,
(r2)Perm(R2)
,
…
,
(rn)Perm(rn)
,构成。
实现代码
1. template<typename T>
2. void Perm(T list[], int k, int m)
3. { //产生list[k:m]的所有排列
4. if(k == m) {
5. //只剩1个元素
6. for(int i = 0; i != m; ++i)
7. cout << list[i];
8. cout << endl;
9. } else { //还有多个元素待排列,递递归产生排列
10. for(int i = k; i != m; ++i) {
11. Swap(list[k], list[i]);
12. Perm(list, k + 1, m);
13. Swap(list[k], list[i]);
14. }
15. }
Swap函数代码
1. template<typename T>
2. inline void Swap(T &a, T &b)
3. {
4. T temp = a;
5. a = b;
6. b = temp;
7. }
实现过程如下图所示,以a元素为例,实现过程如图左,总排列结果如图右。
(4)Hanoi塔问题
如图所示,要求将A上的圆盘移动到B上,上面小圆盘下面大圆盘的顺序不变。
实现代码
1. void hanoi(int n, int a, int b, int c)
2. {
3. if(n > 0) {
4. hanoi(n - 1, a, c, b);
5. move(a, b);
6. hanoi(n - 1, c, b, a);
7. }
8. }
实现过程为首先将A中除最下面的圆盘移动到C上(借助B),然后将A中最下面的圆盘移动到B上,之后将C上的圆盘按顺序移动到B上(借助A)。