Hanoi塔来啦~~
题干:
补充题干不清楚的地方:n只碟子是自下而上由小到大堆叠的!
为了方便理解我们这里有一个小游戏,大家有兴趣的话可以玩玩
链接:https://pan.baidu.com/s/1IGSI4BGvyAZ3y5hzys2IZQ
提取码:zhjk
然后我们进入正题
考虑简单的情况:
一个盘子:X->1->Z
两个盘子:X->1->Y、X->2->Z、Y->1->Z
这两个过程很简单
那么三个盘子呢?
有兴趣的可以试着手推一下,不过我们要开始讲基本算法了。
前面已经提到过,递归的想法其实写成代码很简单,但如果硬要动脑筋去搅脑瓜子就很麻烦。
基本算法:
我们直接找出n等于各种值的时候的相似性,递归其实也是因为很多步骤的重复,才可以用到自身调用自身。
可以得出每最后几步都是先将n-1移到备用柱子(Y杆),然后将第n个移到目的柱子,最后把n-1个盘子移到目的柱子n的上面。
其实这样想很简单,实现代码也简单。
but!
深入懂得其中的道理就是另一回事了。比如我就疑惑了很久,”只能将小的盘子叠在大的盘子上面“,这句话如何实现??
ok!
我们来看,为什么要将n-1移动到备用柱子呢?其实就是因为n更大,应该先移动,然后让较小的n-1移动到它上面。这里就实现了将小的叠在大的上面,所以每一次的移动都相当于n取不同值。这里我们就找到了递归的关键要素之一——重复调用部分,也是由前式推出下一步的关系式。
那么,递归出口是什么呢?
其实上面简单案例就已经说了,当n等于1时,直接将盘子移动到目的柱子。
分析到这里,就可以写代码了!
#include<stdio.h>
//把n个盘子从X移到Z
void hanoi(int n,char X,char Y,char Z);//函数声明
void move(int n,char X,char Z);
int main(){
int n;
scanf("%d",&n);
hanoi(n,'X','Y','Z');
return 0;
}
void hanoi(int n,char X,char Y,char Z){
if(n==1){//n=1时
move(n,X,Z);//直接移动到目的柱子
}
else{
hanoi(n-1,X,Z,Y);//将n-1个盘子移动到备用柱子
move(n,X,Z);//将第n个移动到目的柱子
hanoi(n-1,Y,X,Z); //将n-1个盘子从备用柱子移动到目的柱子
}
}
void move(int n,char X,char Z){//这是移动盘子的函数
printf("%d:%c-->%c",n,X,Z);
printf("\n");
}
//是不是觉得代码的实现蛮简单的,可就是想不到,hhhh
这里呢贴一个n=3时的运行分析
可以自己画图理解一下那个堆栈过程和栈内存释放的过程!
其实我的感觉是,只要懂了就挺简单的,所以我的分析好像也不是很详细。
暂时不能理解也没关系,善用搜索,各种资源总有能讲清楚的。
加油!
希望这些文字能对你有用。
后续我可能会更几道递归的题。
现在还没到时间晚安!嘻嘻