递归——汉诺塔问题的讲解

汉诺塔问题起源于很久很久以前(反正很久)的一个古印度神话,印度教的创造之神梵天,在创造世界的时候创造出了三根金刚石柱子(钻石柱子嘛),其中一个上面有64个黄金圆环,按照从小到大的顺序套在上面,如下图,梵天命令一个叫婆罗门的教徒将所有的圆环移动到另外一个柱子上,并且满足如下规则:

  • 每次只能移动柱子最顶端的一个圆盘;
  • 每个柱子上,小圆盘永远要位于大圆盘之上;

图像如下

要我们算出次数最少的移动路径并且计算次数,看起来确实是一个极其困难的问题,那么,我们如何用代码解决这个问题呢?

1.简化问题;

我们先看下面这个草图,我们将三根柱子标号:a,b,c.原本的圆环在a柱子上面,我们要在满足规则的情况下将其移动到c柱子上面,那我们就将这种 移动模式 记作:

a->c的汉诺塔移动(纯属方便后面的讲解)

然后,无论上面有多少个圆环,我们先将他们分成两个部分(上面的所有圆环当作一个整体,和最下面的环) ,等价于只有两个圆环的汉诺塔问题。

2.分析简单的情况

在1的简化下,我们先来好好分析只有两层的汉诺塔问题,显然最简单的走法是:

将a上面的小环移动到b(中间柱)上,再将a下面的大环移动到c(目标柱)上,然后把b上的小环移动到大环上。

总共三步;

3.将这个情况进行推广:

在2的情况下,我们第一步需要将a上面的环移动到b上面,假如最开始有n个环,第一次是a->c的n环汉诺塔问题,第二次呢?将n-1个环移动到b上面,是不是可以写成a->b的n-1环汉诺塔问题,注意了,此时c柱上面没有环,完全可以充当中间柱,然后呢?a->b的n-1环汉诺塔问题的第一步,是不是a->c的n-2次汉诺塔问题?我们似乎找到规律了

4.转换成代码的形式:

void hannoi(n,a,b,c)//按照:最大环数,开始柱子,中间柱子,最后柱子排列.
{
    hannoi(n - 1, a, c, b);

}

那么这就是必不可少的一部分,但是我们只是做了第一步呀,还要干什么?没错,我们把上面的环拿了下来到了中间柱子上面,接下来是不是移动最下面的大环?所以我们编写一个叫做move的函数表示移动了大环

​
void Move(int n, char a, char c)
{
	printf("%d from %c to %c\n", n, a, c);
}

​

 这就完成了第一次大环移动了,然后我们需要怎么样?上面的环都到了b(上一阶段的中间柱)上,这个时候是不是重复一次上面的过程,把a当作中间柱子,再移动一次最下面的环?

void Han(int n, char x, char y, char z)
{
	if(n==1)
		Move(1, x, z);
	else
	{
		Han(n - 1, x, z, y);
		Move(n, x, z);
		Han(n - 1, y, x, z);
	}
}

如图,最后设置退出递归的条件,就是只剩下一块板子的时候。

在一次次简化下,一道题目就这样解决了(虽然仍然有一定的思考维度)

谢谢大家!完整代码如下:

#include <stdio.h>  
#include <string.h>
#define N 3

void Han(int n, char a, char b, char c);
void Move(int n, char src, char dst);

void main()
{
	Han(N, 'A', 'B', 'C');
}

void Han(int n, char a, char b, char c)
{
	if(n==1)
		Move(1, a, c);
	else
	{
		Han(n - 1, a, c, b);
		Move(n, a, c);
		Han(n - 1, b, a, c);
	}
}

void Move(int n, char a, char c)
{
	printf("%d from %c to %c\n", n, a, c);
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值