递归应用:汉诺塔问题


一、问题描述:Hanoi塔是什么

假设有3个分别命名为A、B和C的塔座,在塔座A上插有n个直径从上至下从大到小的圆盘,编号为1,2,…n。现要将A轴上的n个圆盘移至塔座C并按照同样的顺序叠排。

  1. 每次只能移动一个圆盘。
  2. 圆盘可插在A、B和C中任一塔座上。
  3. 任何时刻都不能将一个较大的圆盘压在较小的圆盘上。
    在这里插入图片描述

二、解决思路

1 简单案例

先来解决n较小时,n = 3时的情况:
在这里插入图片描述
如图我们可以轻易解出:
step1:将A上1号盘移至C,step2:将A上2号盘移至B,step3将C上1号盘移至B,step4:将A上3号盘移至C,step5:将B上1号盘移至A,step6:将B上2号盘移至C,step7:将A上1号盘移至C;完毕。

2 步骤分析

如上案例,我们可发现,当n=1时,只要将A上1号圆盘移至C即可,而n>1时则需要将第n号盘上n-1个盘借助C移动至B,再将n号盘移至C上,而此时B上的n-1号盘上n-2个盘又可借C移至A,而第n-1号则可移至C,此时状态如下
在这里插入图片描述
从中我们不难发现,此时又回到了初始状态,又可通过同样的方法将第n-2号移至C上。是一个很典型的递归算法。

3.伪算法

据上述归纳分析可写出如下递归伪算法(引用《郝斌数据结构》)

if(n>1{
	先把A柱子上的前n-1个盘子从A借助C移至B
	将A柱子上的第n个盘子直接移到C
	再将B柱子上的n-1个盘子借助A移至C
}

三、具体代码

#include <stdio.h>
void move(char A,int n,char C) {
	printf("\t将%d号盘从%c移至%c\n", n, A, C);
	
};

void hanoita(int n, char A, char B, char C) {
	if (n == 1)
		move(A, 1, C);  
	else {
		hanoita(n - 1, A, C, B);  //n>1时将1至n-1号盘借助C移至B
		move(A, n, C); //将n号盘移至C
		hanoita(n - 1, B, A, C);// 将B上1至n-1号盘借助A移至C,这里看作一个位置循环ACB,BAC,即将
								// B赋给下个递归函数的A,就可以将n-1个盘分解为n-1号盘与n-2个盘,循环递归。
	}
}

int main() {
	int num = 0;
	char A='A', B = 'B', C = 'C';
	printf("*******汉诺塔问题*******\n");
	printf("初始A柱上有圆盘数:n = ");
	scanf_s("%d", &num);
	printf("\n步骤如下:\n\n");
	hanoita(num, A, B, C);
}

运行结果

在这里插入图片描述
在这里插入图片描述
不然发现其步骤次数为: 2 n − 1 2^n-1 2n1,n为初始圆盘的个数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值