class-notes/汉诺塔.md
2025-04-03 11:03:28 +08:00

112 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

```c
/*
这段代码实现的是经典的 汉诺塔问题 的递归解法。
汉诺塔问题 是一个数学问题,具体描述如下:
给定三个柱子A、B、C
有若干个大小不等的圆盘通常为n个初始时所有圆盘都堆叠在A柱子上从小到大按顺序叠放
目标是将这些圆盘从A柱子移动到C柱子上并且每次只能移动一个圆盘且大的圆盘不能放在小的圆盘上面。
在这段代码中hanoi 函数递归地解决了这个问题,参数 n 表示要移动的圆盘数x、y、z 分别表示源柱子、辅助柱子和目标柱子。
代码详解:
基本思路:
如果只有一个盘子n == 1直接从 x 移动到 z。
如果有多个盘子n > 1可以通过以下步骤完成 先将前 n-1 个盘子从 x 移到 y这时 z 作为辅助柱子。
将第 n 个盘子从 x 移动到 z。
最后将 n-1 个盘子从 y 移到 z这时 x 作为辅助柱子。
函数 hanoi 的参数:
n表示要移动的圆盘的数量。
x源柱子。
y辅助柱子。
z目标柱子。
递归过程:
对于每个递归调用,问题规模逐渐减小,最终会到达只有一个盘子的情况(基准条件)。
程序输出:
A -> C
A -> B
C -> B
这个输出表示了将两个圆盘从A柱子移动到C柱子所需的步骤。输出结果每一行表示一个移动的操作。
总结:
这段代码是解决汉诺塔问题的经典递归解法。通过分而治之的策略,把问题分解为更小的子问题来求解。
*/
```
### 函数递归打印汉诺塔移动步骤
```c
#include <stdio.h>
/*
n:盘片数
x:源柱子
y:中间柱子
z:目标柱子
判断盘子个数:
如果只有一个盘子,那么直接搬到目标柱子
否则先将上面的n-1的盘子通过目标柱子移
动到非目标柱子上后再将剩下的最大的盘子移动到目标柱子
*/
//n的盘子从x通过y移动到z
void hanoi(int n, char x, char y, char z){
if(n == 1){
printf("%c -> %c\n", x, z);
}else{
hanoi(n-1, x, z, y);
printf("%c -> %c\n", x, z);
hanoi(n-1, y, x, z);
}
}
int main(void){
hanoi(3, 'A', 'B', 'C');
return 0;
}
```
### 函数递归求汉诺塔移动的次数
```c
#include <stdio.h>
/*
n:盘片数
x:源柱子
y:中间柱子
z:目标柱子
判断盘子个数:
如果只有一个盘子,那么直接搬到目标柱子
否则先将上面的n-1的盘子通过目标柱子移
动到非目标柱子上后再将剩下的最大的盘子移动到目标柱子
*/
//n的盘子从x通过y移动到z
//int count = 0;//移动盘片的次数
//而不是只经过B柱子的次数
int hanoi(int n, char x, char y, char z){
int count = 0;//局部变量 用来存储当前这次函数调用中的移动盘子的次数
if(n == 1){
//printf("%c -> %c\n", x, z);
count++;
}else{
count += hanoi(n-1, x, z, y);
//printf("%c -> %c\n", x, z);
count++;
count += hanoi(n-1, y, x, z);
}
return count;
}
int main(void){
printf("%d\n", hanoi(3, 'A', 'B', 'C'));
return 0;
}
```