- ⛩️博主主页:@威化小餅干
- 系列专栏:【数据结构与算法】
- 绳锯⽊断,⽔滴⽯穿!一个编程爱好者的学习记录!
汉诺塔(Tower of Hanoi)
,又称河内塔
,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。不论白天黑夜,总有一个僧侣在移动这些圆盘,一次只移动一个,小的圆盘必须在大的上面。僧侣们预言,当所有的圆盘都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而庙宇和众生也都将同归于尽……
设左为A
,中间为B
,右为C
。
1、当柱子上只有一个圆盘时(即n=1),就非常简单,直接从左边(A)
移动到右边(C)
即可。
2、当柱子上有两个圆盘时(即n=2)
左(A)
移动到中间(B)
右边(C)
中间(B)
的小圆盘移动到右(C)
3、当柱子上有三个圆盘时(即n=3),这个时候如果我们一个一个地去分析,情况就开始变得有点复杂了。
左(A)
先移动到中间(B)
(它俩怎样移动先不考虑)右边(C
中间(B)
的两个圆盘移动到右边(C
)左(A)
的两个圆盘通过右(C)
移动到中间(B)
中间(B)
的两个圆盘通过左(A)
移动到右(C)
4、顺着这样的思路
n-1个看作一个整体
,通过右(C)
移动到中间(B)
右边(C)
中间(B)
n-1个圆盘又可以把上面的n-2个圆盘继续用递归的思想
继续拆分,直到圆盘全部移动到右边(C)
1、第一步移动n-1
小盘子从左(A)移动到中间(B)(又可以递归)
出第一、二、三步,一直递推,直到左(A)上除了底下那个外,其它全部移动到中间(B)
2、第二步移动第n
个小盘子从左(A)移动到右(C)(直接实现)
3、第三步移动n-1
小盘子从中间(B)移动到右(C)(又可以递归)
出第一、二、三步,一直递推,直到中间(B)上的圆盘全部的圆盘全部移动到右(C),结束!
整体
,再把n-2个圆盘看作一个整体,再把…,直到达到结束条件!大化小,繁化简
。函数栈帧上开辟一块空间
,一直递推
,直到遇到结束条件。递推关系和结束条件
。#define _CRT_SECURE_NO_WARNINGS 1
#include
void Hanoi(int n, char A, char B, char C)//将n个圆盘从左边(A)借助中间(B)全部移动到右边(C)
{
if (n == 1)//当只有1个圆盘时
printf("%c->%c\n", A, C);//直接将左边(A)的圆盘移动到右边(C)
else//当n>=2时
{
Hanoi(n - 1, A, C, B);//将左边(A)上面的n-1个圆盘借助右边(C)移动到中间(B),
//一直递推,直到左(A)上除了底下那个外,其它全部移动到中间(B)
printf("%c->%c\n", A, C);//将左边(A)上剩下的1个圆盘移动到右边(C)
Hanoi(n - 1, B, A, C);//将中间(B)上的n-1个圆盘借助左边(A)移动到右边(C),
//一直递推,直到中间(B)上的圆盘全部的圆盘全部移动到右(C),结束!
}
}
int main()
{
int n = 0;
scanf("%d", &n);//输入n个圆盘
Hanoi(n, 'A', 'B', 'C');
return 0;
}