汉诺塔问题详解【C语言递归】

简介:

汉诺塔问题,即在一个装置上有A,B,C三根杆。在A杆自下而上、由大到小按顺序放置n个圆盘(如下图),我们需要保存原有顺序把A杆上的圆盘全部移到C杆上。

操作过程中,每次只能移动一个圆盘,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

我们就用递归思想来计算该问题中圆盘移动次数和步骤。

思路:

我们先列举几种情况来明确我们的思路:

当圆盘个数 n = 1时:

即只有一个圆盘时,将红色圆盘从所在杆A移动到目标杆C,只需要移动1次即可。

当 圆盘个数 n = 2时:

第一步:把上层的红色圆盘从所在杆A移到中间杆B上。

第二步:把底层的黑色圆盘从所在杆A移动到目标杆C上。

第三步:把红色圆盘从所在杆B上移动到目标杆C上。(如下图)

 当 圆盘个数 n = 3时:

 步骤如下图

我们把黑色上方的蓝色、红色两个圆盘看成一个整体,那么这个过程即可简化成与n=2时相同的情况,只需三步即可。

第一步:把上层的红色和蓝色圆盘从所在杆A移到中间杆B上。

第二步:把底层的黑色圆盘从所在杆A移动到目标杆C上。

第三步:把红色和蓝色圆盘从所在杆B上移动到目标杆C上。

 此时,我们再把红色和蓝色圆盘拆分来看:(上述的三步)

第一步便是n = 2时的情况,只是目标杆进行了改变,从A杆移动到B杆上。

第二步把最底层的圆盘移动到目标杆C上即可,只需要移动一次。

第三步依然是重复n = 2时的情况,从B杆移动到C杆上。

由此,我们可以根据以上三个步骤将其概括为:

n = 1时,移动一次即可。

n > 1时,先将(n - 1)个圆盘看成一个圆盘,将其移动到中间杆上,移动1次最底层的圆盘至目标杆,再将(n - 1)个圆盘从中间杆移到目标杆上。如果(n - 1)> 1的话,则再次重复上述三个步骤。

归纳为公式即:

n = 1时,f(n) = 1;

n > 1时,f(n)= f(n-1)+ 1 + f(n - 1)= 2*f(n - 1)+ 1;

移动次数代码:

#include<stdio.h>
int hanoi_num(int n)
{
	if (n > 1)
	{
		return 2 * hanoi_num(n - 1) + 1;
	}
	else
	{
		return 1;
	}
}
int main()
{
	int n;
	scanf("%d", &n);
	printf("次数为:%d", hanoi_num(n));
	return 0;
}

移动步骤:

根据上述的思路,移动的步骤在于所在杆、中间杆、目标杆这三个杆的转换。

方法步骤与上述移动次数一致:(n > 1时)

第一步:把最底层以上的所有圆盘从A杆移动到B杆上,即所在杆A、中间杆C、目标杆B。

第二步:把最底层的圆盘从所在杆A移动到目标杆C上。直接从所在杆A移动到目标杆C即可。

第三步:把最底层以上的所有圆盘从B杆移动到C杆上,即所在杆B、中间杆A、目标杆C。

如果最底层以上的所有圆盘的数量 > 1时,再分别重复上述步骤。

代码如下:

#include<stdio.h>
void hanoi_move(int n, char A, char B, char C)
//参数A,B,C分别为所在杆,中间杆,目标杆
{
	if (n > 1)
	{
		//传入的参数为当前情况下的所在杆,中间杆,目标杆
		hanoi_move(n - 1, A, C, B);
		printf("%c -> %c\n",A,C);
		hanoi_move(n - 1, B, A, C);
	}
	else
	{
		printf("%c -> %c\n",A,C);
	}
}
int main()
{
	int n;
	scanf("%d", &n);
	hanoi_move(n,'A','B','C');
	return 0;
}

作为一名C语言初学者,有表述不清,还请多包涵。如有错误,欢迎指正。

  • 22
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
汉诺塔问题是经典的递归问题,它的求解过程可以用递归算法来实现。以下是汉诺塔问题C语言递归算法分析。 1. 问题描述 汉诺塔问题是指有三根柱子A、B、C,在A柱子上从下往上按照大小顺序放置n个盘子,要求把这n个盘子移动到C柱子上,移动过程中可以借助B柱子,但是要满足以下条件: 1. 每次只能移动一个盘子; 2. 盘子不能放在比它小的盘子上面。 2. 递归实现 汉诺塔问题可以通过递归实现,具体实现过程如下: 1. 将n-1个盘子从A柱子移动到B柱子上,借助C柱子; 2. 将A柱子上最大的盘子移动到C柱子上; 3. 将n-1个盘子从B柱子移动到C柱子上,借助A柱子。 递归终止条件是只有一个盘子时直接将其从A柱子移动到C柱子上。 3. 代码实现 下面是汉诺塔问题C语言递归算法实现代码: ```c #include <stdio.h> void hanoi(int n, char from, char to, char via) { if (n == 1) { printf("Move disk %d from %c to %c\n", n, from, to); } else { hanoi(n-1, from, via, to); printf("Move disk %d from %c to %c\n", n, from, to); hanoi(n-1, via, to, from); } } int main() { int n = 3; // 三个盘子 hanoi(n, 'A', 'C', 'B'); return 0; } ``` 代码中,hanoi函数用于求解汉诺塔问题,n表示盘子的个数,from表示起始柱子,to表示目标柱子,via表示中介柱子。在函数中,如果n等于1,则直接将盘子从起始柱子移动到目标柱子上;否则,递归地将n-1个盘子从起始柱子移动到中介柱子上,然后将最大的盘子从起始柱子移动到目标柱子上,最后递归地将n-1个盘子从中介柱子移动到目标柱子上。 在main函数中,首先定义了盘子的个数n,然后调用hanoi函数求解汉诺塔问题。 4. 总结 汉诺塔问题是经典的递归问题,通过递归算法可以简便地实现其求解过程。在实现时,需要注意递归的终止条件和递归调用的顺序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值