递归
递归的定义
- 递归指函数在运行期间,直接或间接的调用自己
(就很抽象) - 递归的用法一般用在处理同一类的问题,除了问题的规模大小外,解题方法和思路是一致的
递归的特点
- 先递后归,先把问题分解成规模比原问题小的子问题,分解到不能在分解,得出了结果
- 将最小层结果返回给上一层,层层返回
汉若塔问题
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
感谢知乎大佬的解释
知乎
知乎2
虽然理解的迷迷糊糊 看了一天,能理解部分的原理了
首先我们在理解递归算法和问题的时候要注意一下几点
- 不要试图去跟踪递归遍历的过程和结果
- 我们应该用数据归纳法去归纳相同问题在递归公式
- 找出递归公式
在汉若塔问题中
假设 n是汉若塔盘子数 盘子在初始柱A 中间柱B 目标柱C
对于汉若塔问题,我们将其划分为个步骤
1.将A柱上的盘子除了底部最大的盘子之外的都移动到中间柱B
2. 将A柱的盘子移动到C
3. 将B柱的盘子移动到C
我们通过一系列的试探去获得一些规律
设函数 hanio(n,‘A’,‘B’,‘C’);
当n = 1 n可以直接移动到目标柱C
也就是 A -> C
直接将A柱上的盘子移动到C
当 n = 2
A - > B,
A -> C
B -> C
当n=2 时 我们需要将 n-个盘子挪到B柱上,剩下个第N个也就是最大的盘子
直接挪到C ,然后在讲N-1个盘子 从B挪到C上
当n>=2 时 函数移动就需要执行三次
我们在看看 n=3时
- 将 N-1个盘子挪到B柱上
- 我们将N-1 也就是2个盘子从A柱子挪到B柱子
- 也就是说 N-1个盘子借助C 挪到目标柱子B
- A -> C
- A -> B
- C ->B
2.将A柱子上剩下的第N个盘子从A移动到目标柱C
- A -> C
- 将N-个柱子从B柱挪到C柱上
-
将B柱子的上n分解 此时 n=2
-
B -> A
-
B -> C
-
A -> C
我们总结归纳 当 move(3,A,B,C)时
应执行以下三步操作
将 n-1个从A-> B
{
- A -> C
- A -> B
- C ->B
}
A->C
将n-1个盘子从B借助A移动到C
{
- B -> A
- B -> C
- A -> C
}
我们发现
第一步和第三步不就是move(2,A,C,B)和(move(2,B,A,C)吗
那相当于move(3,A,B,C)
{
move(2,A,C,B);
printf(“A->C”);
move(2,B,A,C);
}
递归递归在于将问题分解成不可分解 然后将不可分解子问题转为答案返回给上层
像这个三层汉若塔问题 可以分解为三大类
将n-1个移动到B 那么当n-1>=2时是无法直接移动的 所以要继续-1 直到 n=1
但是 n=1的时候和 n=2 时候的目标柱和中间柱是不一样的
通过这个汉若塔问题
我发现递归递归,说白了就是懒人必备的偷懒技能
因为汉若塔每次移动都需要遵守大的再下 小的在上,
每次手动搬实在是麻烦
理解重点
当n>1时 我们需要逐步递减n 就好比汉若塔想要搬动第N个 要将N-1个挪走 逐步递减
逐步搬运
代码
#include<stdio.h>
#include<stdlib.h>
void Hanio(int n,char A,char B, char C);
int main()
{
printf("请输入汉若塔盘子数n:\n");
int n;
scanf("%d",&n);
Hanio(n,'A','B','C');
return 0;
}
void Hanio(int n,char A,char B, char C)
{
if(n==1)
{
printf("%c->%c\n",A,C);
}else{
Hanio(n-1,A,B,C);
printf("%c->%c\n",A,C);
Hanio(n-1,B,A,C);
}
}