C语言 Hanoi(汉诺)塔问题,用递归解决

【问题】
古代有一个梵塔,塔内有3个座A,B,C。开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把64个盘子从A作移到C座,但规定每次只能移动一个盘,且在移动过程中在3个座上都始终保持大盘在下小盘在上。在移到过程中可以利用B座。要求编写程序输出移动盘子的步骤。
【思路】
请添加图片描述
如图所示,先将A座上面的63个盘子借助C座移动到B座,然后把A座上第64 个盘子移动到C座,最后把B座上的63个盘子借助A座移动到C座。
为便于理解,先分析A座有3个盘子的情况,移到前的情况如下图:
请添加图片描述

(1)将A座上2个盘子借助C座移动到B座请添加图片描述
(2)将A座上1个盘子移动到C座
请添加图片描述
(3)将B座上的盘子借助A座移动到C座。
请添加图片描述
其中第(2)步可以直接实现。
第(1)步又可用递归方法分解为:
①将A座1个盘子从A座移到C座
②将A座1个盘子从A座移到B座
③将C座1个盘子从C座移到B座
第(3)步可分解为:
①将B座1个盘子从B座移到A座
②将B座1个盘子从B座移到C座
③将A座1个盘子从A座移到C座
将上述综合起来,移到3个盘子的步骤为:
A->C,A->B,C->B,A->C,B->A,B->C,A->C
共经历了7步。
由此可以推出:移动n个盘子要经历(2^n-1)步。
所以,将n个盘子从A座移到C座可以分解为以下3个步骤:
(1)将A座的(n-1)个盘子借助C座移到B座
(2)将A座剩下的一个盘子移动到C座
(3)将B座的(n-1)个盘子借助A座移到C座
上面的第(1)步和第(3)步,都是把n-1个盘子从一个座移到另一个座,采取的办法是一样的,只是座的名字不同而已。所以将第(1)步和第(3)步表示为:
将one座上n-1个盘子借助three座移到two座。
只是在第(1)步和第(3)步中,one,two,three和A,B,C的对应关系不同。
对于第(1)步:
对应关系是one对应A,two对应B,three对应C。
对于第(3)步:
对应关系是one对应B,two对应C,three对应A。
因此,可以把上面的3个步骤分解成两类操作:
(1)将(n-1)盘从一个座移到另一个座,这是一个递归过程。
(2)将一个盘子从一个座移到另一个座。
【编写程序】
分别用两个函数实现以上两类操作。
用Hanoi函数实现(1)
用Move函数实现(2)
函数调用Hanoi(n,one,two,three)表示将n个盘子从one座借助two座移到three座的过程
函数调用Move(x,y)表示将1个盘子从x座移到y座的过程
【代码实现】

void Move(char x, char y)
{
	printf("%c->%c\n", x, y);
}
void Hanoi(int n, char one, char two, char three)
{
	if (n == 1)
		Move(one, three);
	else
	{
		Hanoi(n - 1, one, three, two);
		Move(one, three);
		Hanoi(n - 1, two, one, three);
	}

}
int main()
{
	int number;
	printf("请输入要移到的盘子的数量:\n");
	scanf("%d", &number);
	printf("移动盘子的步骤为:\n");
	Hanoi(number, 'A', 'B', 'C');
	return 0;
}

【输出结果】
请添加图片描述
【程序分析】
调用递归函数Hanoi,其终止条件是Hanoi函数的参数n的值等于1。显然,此时不必再调用Hanoi函数了,直接执行Move函数即可。
Move函数并未真正的移动盘子,而只是输出移动盘子的步骤。
前面提到将64个盘子从A座移到C座需要移动(2^64-1)次,假设每次移动一个盘子需要1秒,则移动
(2^64-1)次需要大约600亿年。
所以程序中以3个盘子为例,而不是64个盘子。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值