最近程序设计老师讲到了递归的用法,以及留下一道汉诺塔的问题让我们解决,此篇博客便是对汉诺塔问题的一个总结,如果有不正确的地方还请大家指正。
汉诺塔问题是一个很经典的递归问题,对于入门递归而言很有帮助。下面我们进入题目。
汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从上往下从小到大顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘,只能移动在最顶端的圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。
简单的理解就是让一个柱子上的环通过一个辅助柱子按顺序移动到另一个柱子上,下面我们对题目进行一个简单的分析。
题目分析:因为我们知道要用递归去解题所以我们开始考虑递归的实现,所以我们考虑一下过程,他的第一步是在A上编号为n的环以B作为辅助移动到C上,下一步A环空了那么该以A环作为辅助将B上编号为n-1的环移动到C上,下一步又与第一步相同以B为辅助环,之后又以A为辅助环了,这样我们便得出了递归的方程的实现,下面我们看终止条件因为我们是n-1的不断的递归所以当n=0 时就就是终止条件。
所以我们的便得出了递归方程
void hanno(int n,char x,char y,char z)
{ if(n==0)
{
return;
}
hanno(n-1,x,z,y);
move(n,x,z);
hanno(n-1,y,x,z);
}
我们下一步改解决让代码的可视化,就是如何让我们看出代码的运作过程,因为递归的过程是在计算机进行,我们无法看到。其实就是一个简单的printf就能解决。因为函数hanno(n,x,y,z)让X的n号环移动到z环,所以printf就输出x–>z再加上前面的的步骤数以及移动的编号那么printf的代码便出现了,虽然是用的C++,但是cout输出太麻烦了,所以我们用printf。
void move(int n,char from,char to)//“step”已经全局定义
{
printf("step %d number %d from %c to %c\n",step++,n,from,to);
}
所以将代码组合一下就出现我们想要的的汉诺塔解法。
#include<bits/stdc++.h>
using namespace std;
int step=1;
void way(int n,char from,char to)
{
printf("step %d number %d from %c to %c\n",step++,n,from,to);
}
void hanno(int n,char x,char y,char z)
{ if(n==0)
{
return;
}
hanno(n-1,x,z,y);//以B柱为辅助柱
way(n,x,z);// 输出步骤
hanno(n-1,y,x,z);//以A柱为辅助柱
}
int main()
{ int n;
cin>>n;
hanno(n,'A','B','C');
}
小小的补充一下这个输出函数的位置讲究,它放在两个递归函数中间正好一个移动结束
就输出了如果放在两个函数下面,则两次移动才会输出一次。
写在最后:汉诺塔其实是一个简单的递归问题,让我们更加深刻的了解递归的应用。因为博主也是初学无法更加深入的分析其中的思想,也可能会有笔误,也请各位的对我的错误进行指正。