递归3之汉诺塔的实现
作者:互联网
汉诺塔的实现
前言
一、汉诺塔是什么?
汉诺塔,又称河内塔,讲的是在一根柱子上从下往上按照大小顺序摞着64片圆盘,要求把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
二、实现思路
1.尝试找出规律
我们假设在柱子上有n个圆盘,三根柱子分别为A,B,C,A为起始柱子,B则是起到中转作用的中转柱子,而C就是目标柱子。先穷举出n较小的一些情况,看看能不能从中找到一些初步的思路和规律。
当n = 1时,我们只需要 A->C
1步
当n = 2时,我们需要 A->B,A->C,B->C
3步
当n = 3时,我们就已需要 A->C,A->B,C->B,A->C,B->A,B->C,A->C
7步
当n=4时,这时再看一下A->B,A->C,B->C,A->B,C->A,C->B,A->B,A->C,B->C,B->A,C->A,B->C,A->B,A->C,B->C
15步
我们发现无论怎么移动,本质上都是先把A上除了最后一个圆盘的其他柱子通过C柱子移到B柱子上,接着把A上最后一个圆盘移动到C上,最后再通过A柱子把B柱子上所有圆盘移动到C柱子上。那么到这个时候我们也就已经得到了基本规律了。
2.代码初步思路
首先我想构造一个函数用来表示圆盘的移动轨迹,即从哪根柱子移动到哪根柱子。
void Move(char pos1, char pos2){
printf( "%c->%c ", pos1, pos2);
}
然后用n来表示圆盘数量,分三步递归汉诺塔
第一步,将A柱子上的圆盘除了最后一个,其余的以C柱子为中转,把A上的圆盘都移动到B圆盘。
第二步,将A柱子上最后的圆盘移动到C柱子上。
第三步,将B柱子上的所有圆盘此时以A柱子为中转移动到C柱子上即可。
void ToH (int n, char pos1, char pos2, char pos3){
if(n == 1){
Move(pos1, pos3);
}
else{
ToH(n - 1, pos1, pos3, pos2);
Move(pos1, pos3);
ToH(n - 1, pos2, pos1, pos3);
}
}
这就是编程时写代码一些思路,仅供参考。
三、最终实现
最终的代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void Move(char pos1, char pos2) {
printf("%c->%c ", pos1, pos2);
}
void ToH(int n, char pos1, char pos2, char pos3) {
if (n == 1) {
Move(pos1, pos2);
}
else {
ToH(n - 1, pos1, pos3, pos2);
Move(pos1, pos3);
ToH(n - 1, pos2, pos1, pos3);
}
}
int main() {
int n;
scanf("%d", &n);
ToH(n, 'A', 'B', 'C');
return 0;
}
在这里我是使用了一个scanf函数可以来控制圆盘的数量,然后列举出每个步骤。如果直接让n=64的话,会有264 -1步,我的电脑CPU是2.5GHz,我们可以来试着计算一下264 /2.5/1024/1024/1024/3600/24/366 = 217.3年,也就是说在我的电脑不间断的运算下,需要217年可以得到整个汉诺塔的步骤,到时候的结果反正我肯定是看不到了。
总结
感觉汉诺塔相比于前面写的青蛙跳台阶和斐波那契数列来说,更具有难度也更有趣一些。汉诺塔不像前两者一样偏于数学运算多一些,汉诺塔更偏向思维方式多一点,你要怎么去移动,如何构造这个模型,如何找到递归公式,都是更具有难度的。
最后如果有什么可以优化或者需要改正的地方,希望大佬可以多多指点。
标签:柱子,递归,实现,char,圆盘,汉诺塔,pos2,pos1 来源: https://blog.csdn.net/weixin_42504087/article/details/117630926