【C语言】汉诺塔问题

目录

一、何为汉诺塔问题?

二、汉诺塔计算规律

三、打印汉诺塔的移动路径

总结


一、何为汉诺塔问题?

汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。

简单来讲,汉诺塔问题是这样的:

给定三根柱子,记为A,B,C,其中 A 柱子上有 n个盘子,从上到下编号为 0 到 n−1 ,且上面的盘子一定比下面的盘子小。问:将A 柱上的盘子经由 B柱移动到 C 柱最少需要多少次?并且移动时还有要求:1、一次只能移动一个盘子 2、大的盘子不能压在小盘子上


二、汉诺塔计算规律

我们分别计算有1个圆盘、2个圆盘、3个圆盘、4个圆盘的情况:

.......

3个圆盘需要移动7次,4个圆盘需要移动15次,我们可以得出规律,得到一条计算公式:

2^n - 1 == 移动次数。用递归计算n个盘子的移动次数,代码如下:

//递归计算n个盘子要移动的次数
int hanoi(int n)
{
	//当只有1个盘子时,移动1次
	if (1 == n)
		return 1;
	//当有n>1时
	//1、将n-1个盘子移到辅助柱子上-->hanoi(n-1)
	//2、然后起始柱子中剩1个盘子,移到目标柱子 --> 1
	//3、最后将辅助柱子上的n-1个盘子移到目标柱子上 -->hanoi(n-1)
	//1和3的移动次数是相同的,因此可以写成-->2*hanoi(n-1)
	else
	{
		return 2 * hanoi(n - 1) + 1;
	}
}
int main()
{

	int count = hanoi(3);
	printf("需要移动:%d\n", count);
	return 0;
}

一直递归下去,直到n-1变为1,此时hanoi(1)就是1(因为只有一个盘子,只需要移动一次)。最终,这个递归过程会展开为一个类似于二叉树的形状,每一层的节点数量都是上一层的两倍(因为每次都将问题分解为两个子问题),而每一层都加上了一个额外的移动(即移动最大的那个盘子)。因此,总的移动次数就是一个等比数列的和,其和可以用公式2^n - 1来表示(其中n是盘子的数量)。这个公式实际上就是2*(n-1) + 1在递归展开后的结果。


三、打印汉诺塔的移动路径

递归打印移动路径,核心思想是大事化小,借助B柱子,一次性移动(n-1)个圆盘到B柱子上,再将A柱子上的圆盘移动到C柱子上,最后再讲B柱子的盘子移到C柱子上,看代码:

//递归方法
//n -- 盘子个数
//post1 -- 起始柱子
//post2 -- 辅助柱子
//post3 -- 目标柱子
void move(char post1,char post2)
{
	printf("%c->%c ", post1, post2);
}
void hanoi(int n,char post1,char post2,char post3) 
{
	//当n==1时,只有一个盘子
	//post1 -> post3 即可
	//递归的终止条件
	if (n == 1)
	{
		move(post1, post3);
	}
	else
	{
		//将n-1个盘子从post1通过post3移动到post2。
		hanoi(n-1, post1, post3, post2);
        // move(post1, post3); 
        //函数的作用是模拟将一个盘子从 post1 柱子移动到 post3 柱子,
        //并打印出这一移动的过程。
		move(post1, post3);
        //将n-1个盘子从post2通过post1移动到post3。
		hanoi(n-1, post2, post1, post3);
	}
}
int main() 
{
	hanoi(2, 'A', 'B', 'C');
	return 0;
}

代码解释:

当盘子数量为1时:我们只需要将它从起始柱子直接移动到目标柱子。这也是递归的终止条件。

当盘子数量大于1时,我们执行以下三个步骤:

  •  将n-1个盘子从post1通过post3移动到post2
  •  将剩下的那个盘子(最大的那个)从post1移动到post3
  •  将n-1个盘子从post2通过post1移动到post3

看图解:


总结

这就是关于汉诺塔问题,关注我!!有更多干货,感谢支持!!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值