递归3之汉诺塔的实现

Posted zsQgqdsd1002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归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年可以得到整个汉诺塔的步骤,到时候的结果反正我肯定是看不到了。


总结

感觉汉诺塔相比于前面写的青蛙跳台阶和斐波那契数列来说,更具有难度也更有趣一些。汉诺塔不像前两者一样偏于数学运算多一些,汉诺塔更偏向思维方式多一点,你要怎么去移动,如何构造这个模型,如何找到递归公式,都是更具有难度的。

最后如果有什么可以优化或者需要改正的地方,希望大佬可以多多指点。

以上是关于递归3之汉诺塔的实现的主要内容,如果未能解决你的问题,请参考以下文章

7-17 汉诺塔的非递归实现

习题3.10 汉诺塔的非递归实现(25 分)浙大版《数据结构(第2版)》题目集

汉诺塔的非递归实现(借助堆栈模拟递归)

7-17 汉诺塔的非递归实现 (25分)

汉诺塔的非递归实现(栈)

汉诺塔的递归算法